matryer / moq

Interface mocking tool for go generate
http://bit.ly/meetmoq
MIT License
2k stars 127 forks source link

Moq panics when trying to mock function which returns imported type #123

Closed QuantumBJump closed 4 years ago

QuantumBJump commented 4 years ago

I have an interface in one of my packages with the structure

//go:generate moq -out mock_persistence_data_test.go . persistenceClient
type persistenceClient struct {
  EnsureSchema()
  GetUnfinishedSchedules() (*[]persistence_data.ScheduleRequest, error)
}

Recently, moq has suddenly started panicking whenever I try to run go generate, and I can't work out why. I have managed to work out that it only happens when there's a function in the mocked interface which returns a type imported from a different package, but I can't work out why it's a problem. The error messages in themselves are unhelpful - I get a go/format: expected ), got type error, followed by the moq usage string, followed by running "moq": exit status 1

It's starting to look like our only option is to refactor the entire program to not use moq any more, which is something I'm loathe to do...

sudo-suhas commented 4 years ago

Can you please share a repo or zip file with which I can reproduce the issue? I tried to do so but the mock was generated correctly without any problem.

-- testmock/issue123/persistence_client.go

package issue123

import "testmock/issue123/persistence_data"

//go:generate moq -out mock_persistence_data_test.go . persistenceClient
type persistenceClient interface {
  EnsureSchema()
  GetUnfinishedSchedules() (*[]persistence_data.ScheduleRequest, error)
}

-- testmock/issue123/persistence_data/schedule_req.go

package persistence_data

type ScheduleRequest int
-- testmock/issue123/mock_persistence_data_test.go ```go // Code generated by moq; DO NOT EDIT. // github.com/matryer/moq package issue123 import ( "sync" "testmock/issue123/persistence_data" ) var ( lockpersistenceClientMockEnsureSchema sync.RWMutex lockpersistenceClientMockGetUnfinishedSchedules sync.RWMutex ) // Ensure, that persistenceClientMock does implement persistenceClient. // If this is not the case, regenerate this file with moq. var _ persistenceClient = &persistenceClientMock{} // persistenceClientMock is a mock implementation of persistenceClient. // // func TestSomethingThatUsespersistenceClient(t *testing.T) { // // // make and configure a mocked persistenceClient // mockedpersistenceClient := &persistenceClientMock{ // EnsureSchemaFunc: func() { // panic("mock out the EnsureSchema method") // }, // GetUnfinishedSchedulesFunc: func() (*[]persistence_data.ScheduleRequest, error) { // panic("mock out the GetUnfinishedSchedules method") // }, // } // // // use mockedpersistenceClient in code that requires persistenceClient // // and then make assertions. // // } type persistenceClientMock struct { // EnsureSchemaFunc mocks the EnsureSchema method. EnsureSchemaFunc func() // GetUnfinishedSchedulesFunc mocks the GetUnfinishedSchedules method. GetUnfinishedSchedulesFunc func() (*[]persistence_data.ScheduleRequest, error) // calls tracks calls to the methods. calls struct { // EnsureSchema holds details about calls to the EnsureSchema method. EnsureSchema []struct { } // GetUnfinishedSchedules holds details about calls to the GetUnfinishedSchedules method. GetUnfinishedSchedules []struct { } } } // EnsureSchema calls EnsureSchemaFunc. func (mock *persistenceClientMock) EnsureSchema() { if mock.EnsureSchemaFunc == nil { panic("persistenceClientMock.EnsureSchemaFunc: method is nil but persistenceClient.EnsureSchema was just called") } callInfo := struct { }{} lockpersistenceClientMockEnsureSchema.Lock() mock.calls.EnsureSchema = append(mock.calls.EnsureSchema, callInfo) lockpersistenceClientMockEnsureSchema.Unlock() mock.EnsureSchemaFunc() } // EnsureSchemaCalls gets all the calls that were made to EnsureSchema. // Check the length with: // len(mockedpersistenceClient.EnsureSchemaCalls()) func (mock *persistenceClientMock) EnsureSchemaCalls() []struct { } { var calls []struct { } lockpersistenceClientMockEnsureSchema.RLock() calls = mock.calls.EnsureSchema lockpersistenceClientMockEnsureSchema.RUnlock() return calls } // GetUnfinishedSchedules calls GetUnfinishedSchedulesFunc. func (mock *persistenceClientMock) GetUnfinishedSchedules() (*[]persistence_data.ScheduleRequest, error) { if mock.GetUnfinishedSchedulesFunc == nil { panic("persistenceClientMock.GetUnfinishedSchedulesFunc: method is nil but persistenceClient.GetUnfinishedSchedules was just called") } callInfo := struct { }{} lockpersistenceClientMockGetUnfinishedSchedules.Lock() mock.calls.GetUnfinishedSchedules = append(mock.calls.GetUnfinishedSchedules, callInfo) lockpersistenceClientMockGetUnfinishedSchedules.Unlock() return mock.GetUnfinishedSchedulesFunc() } // GetUnfinishedSchedulesCalls gets all the calls that were made to GetUnfinishedSchedules. // Check the length with: // len(mockedpersistenceClient.GetUnfinishedSchedulesCalls()) func (mock *persistenceClientMock) GetUnfinishedSchedulesCalls() []struct { } { var calls []struct { } lockpersistenceClientMockGetUnfinishedSchedules.RLock() calls = mock.calls.GetUnfinishedSchedules lockpersistenceClientMockGetUnfinishedSchedules.RUnlock() return calls } ```
QuantumBJump commented 4 years ago

Ok, it looks like I've managed to fix the issue, although I don't know why the problem was happening or why what I did fixed it - I had a shell script running whenever I made a merge request to my project, which ran go get moq, generated the mocks and ran the tests.

For some reason this started failing at some point (although I didn't make any changes relating to that part of the codebase), and the solution was to remove the go get github.com/matryer/moq call from the shell script, as the computer running it already had moq installed. My best guess is that maybe it was the fact it was being run in the project source directory itself might have been a problem? That or the fact that my project uses go modules and I don't think moq does... Either way, this problem seems to be resolved (if unsatifactorily) for my use case.