Go 模拟测试文件中定义的接口:“接口”;未定义的“;?

Go 模拟测试文件中定义的接口:“接口”;未定义的“;?,go,go-testing,Go,Go Testing,这是一个我试图用最少的例子重现的bug,但迄今为止没有成功。Go模块与以下类似: . ├── go.mod └── handler ├── handler.go ├── handler_test.go └── mock_handler.go . ├── cmd │   └── root.go ├── images ├── main.go └── vpp ├── ensure_license_test.go └── mock_handler.go 其中h

这是一个我试图用最少的例子重现的bug,但迄今为止没有成功。Go模块与以下类似:

.
├── go.mod
└── handler
    ├── handler.go
    ├── handler_test.go
    └── mock_handler.go
.
├── cmd
│   └── root.go
├── images
├── main.go
└── vpp
    ├── ensure_license_test.go
    └── mock_handler.go
其中
handler.go
为空(仅包含
package handler
),
handler\u test.go
包含
handler
接口定义(与go的
http.handler
相同)和占位符测试

package handler

import (
    "net/http"
    "testing"
)

type Handler interface {
    ServeHTTP(http.ResponseWriter, *http.Request)
}

func TestMockHandler(t *testing.T) {
    mockHandler := MockHandler{}
    t.Log(mockHandler)
}
mock_handler.go
包含一个
MockHandler
结构,该结构实现
handler
接口,并使用以下方法生成:

为了生成
mock_handler.go
,我首先在
handler.go
中定义了
handler
,然后在
handler
目录中运行命令

 moq -out mock_handler.go . Handler
我随后将
Handler
接口定义移动到
Handler\u test.go
,因为它只用于测试

在这个简化的示例中,我能够在根目录下以包列表模式运行
go test

~/g/s/g/k/mockhandler> go test ./... -count=1
ok      github.com/kurtpeek/mockhandler/handler 0.448s
我的“实际”模块具有类似的结构,如下所示:

.
├── go.mod
└── handler
    ├── handler.go
    ├── handler_test.go
    └── mock_handler.go
.
├── cmd
│   └── root.go
├── images
├── main.go
└── vpp
    ├── ensure_license_test.go
    └── mock_handler.go
Handler
接口的定义方式与简化模块中的
sure\u license\u test.go
中的
Handler\u test.go
完全相同<代码>确保许可证测试。开始时如下所示:

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
与简化模块中的
mock_handler.go
完全相同(包名除外)

然而,当我在“实际”模块的根目录中运行
go test./…
时,我得到
处理程序的
未定义的
错误:

~/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
var _ http.Handler = &MockHandler{}
奇怪的是,当我在
vpp
包中运行这个时,它传递:

> go test ./... -count=1
ok      github.com/fleetsmith/vpp-client/vpp    0.601s

在第一个示例中,当从根目录以包列表模式运行
处理程序时,
go test
无法定义
处理程序的定义,这可能是什么原因?

结果表明,测试失败的是
cmd
包,因为它无法导入
处理程序
来自
vpp
包中测试文件的接口。因此,我将
mock_handler.go
的第17行更改为使用
http.handler
而不是
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
var _ http.Handler = &MockHandler{}
现在测试通过了:

~/g/s/g/f/vpp-client> go test ./...
?       github.com/fleetsmith/vpp-client    [no test files]
?       github.com/fleetsmith/vpp-client/cmd    [no test files]
ok      github.com/fleetsmith/vpp-client/vpp    0.462s
我还可以从
sure\u license\u test.go
中删除
Handler
接口的定义,因为我现在直接使用
http
标准库中的定义


这种方法的缺点是需要编辑由
moq
自动生成的代码,我无法弄清楚如何在Go的标准库中运行
moq
来模拟接口,在任何情况下,该接口都不太可能更改。

没有在测试文件中声明的正常源文件引用标识符。如果需要在源文件中引用
处理程序
,只需在源文件中声明即可。为什么?因为导入包时只导入源文件,不是测试文件,如果其中一个源文件引用了导入中未包含的测试文件中声明的标识符,则会出现未定义的编译器错误。这意味着当您执行
go test./…
时,失败的不是
vpp
包,而是其他包之一,导入
vpp
,但失败的程序。