This is a bug which I've attempted to reproduce with a minimal example, but so far unsuccessfully. The Go module is similar to the following:
.
├── go.mod
└── handler
├── handler.go
├── handler_test.go
└── mock_handler.go
where handler.go
is empty (contains package handler
only), handler_test.go
contains a Handler
interface definition (which is the same as Go's http.Handler
) and a placeholder test,
package handler
import (
"net/http"
"testing"
)
type Handler interface {
ServeHTTP(http.ResponseWriter, *http.Request)
}
func TestMockHandler(t *testing.T) {
mockHandler := MockHandler{}
t.Log(mockHandler)
}
and mock_handler.go
contains a MockHandler
struct which implements the Handler
interface and is generated using moq
:
// Code generated by moq; DO NOT EDIT.
// github.com/matryer/moq
package handler
import (
"net/http"
"sync"
)
var (
lockMockHandlerServeHTTP sync.RWMutex
)
// Ensure, that MockHandler does implement Handler.
// If this is not the case, regenerate this file with moq.
var _ Handler = &MockHandler{}
// MockHandler is a mock implementation of Handler.
//
// func TestSomethingThatUsesHandler(t *testing.T) {
//
// // make and configure a mocked Handler
// mockedHandler := &MockHandler{
// ServeHTTPFunc: func(in1 http.ResponseWriter, in2 *http.Request) {
// panic("mock out the ServeHTTP method")
// },
// }
//
// // use mockedHandler in code that requires Handler
// // and then make assertions.
//
// }
type MockHandler struct {
// ServeHTTPFunc mocks the ServeHTTP method.
ServeHTTPFunc func(in1 http.ResponseWriter, in2 *http.Request)
// calls tracks calls to the methods.
calls struct {
// ServeHTTP holds details about calls to the ServeHTTP method.
ServeHTTP []struct {
// In1 is the in1 argument value.
In1 http.ResponseWriter
// In2 is the in2 argument value.
In2 *http.Request
}
}
}
// ServeHTTP calls ServeHTTPFunc.
func (mock *MockHandler) ServeHTTP(in1 http.ResponseWriter, in2 *http.Request) {
if mock.ServeHTTPFunc == nil {
panic("MockHandler.ServeHTTPFunc: method is nil but Handler.ServeHTTP was just called")
}
callInfo := struct {
In1 http.ResponseWriter
In2 *http.Request
}{
In1: in1,
In2: in2,
}
lockMockHandlerServeHTTP.Lock()
mock.calls.ServeHTTP = append(mock.calls.ServeHTTP, callInfo)
lockMockHandlerServeHTTP.Unlock()
mock.ServeHTTPFunc(in1, in2)
}
// ServeHTTPCalls gets all the calls that were made to ServeHTTP.
// Check the length with:
// len(mockedHandler.ServeHTTPCalls())
func (mock *MockHandler) ServeHTTPCalls() []struct {
In1 http.ResponseWriter
In2 *http.Request
} {
var calls []struct {
In1 http.ResponseWriter
In2 *http.Request
}
lockMockHandlerServeHTTP.RLock()
calls = mock.calls.ServeHTTP
lockMockHandlerServeHTTP.RUnlock()
return calls
}
In order to generate mock_handler.go
, I initially defined the Handler
in handler.go
and then, in the handler
directory, ran the command
moq -out mock_handler.go . Handler
I subsequently moved the Handler
interface definition to handler_test.go
since it is only intended to be used for tests.
In this simplified example, I'm able to run go test
in package list mode in the root directory:
~/g/s/g/k/mockhandler> go test ./... -count=1
ok github.com/kurtpeek/mockhandler/handler 0.448s
My 'actual' module has a similar structure, similar to the following:
.
├── cmd
│ └── root.go
├── images
├── main.go
└── vpp
├── ensure_license_test.go
└── mock_handler.go
The Handler
interface is defined in exactly the same way in ensure_license_test.go
as in handler_test.go
in the simplified module; ensure_license_test.go
starts like this:
package vpp
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type Handler interface {
ServeHTTP(http.ResponseWriter, *http.Request)
}
type MockTestServer struct {
TestServer *httptest.Server
MockHandler *MockHandler
}
mock_handler.go
is also exactly the same as mock_handler.go
in the simplified module (except for the package name).
Yet when I run go test ./...
in the root directory of the 'actual' module, I get an undefined
error for Handler
:
~/g/s/g/f/vpp-client> go test ./... -count=1
# github.com/fleetsmith/vpp-client/vpp
vpp/mock_handler.go:17:7: undefined: Handler
ok github.com/fleetsmith/vpp-client/vpp 0.128s
Strangely, when I run this from within the vpp
package, it passes:
> go test ./... -count=1
ok github.com/fleetsmith/vpp-client/vpp 0.601s
What could be the reason that go test
is unable to define the definition of Handler
when running it in package list mode from the root directory as in the first example?