更新,2023年6月:不再维护此存储库和工具。请参阅go.uber.org/mock,以获取维护的叉子。
Gomock是GO编程语言的模拟框架。它与GO的内置testing
软件包相结合,但也可以在其他情况下使用。
安装后,安装mockgen
工具。
注意:如果您没有这样做,请确保在您的PATH
中添加$GOPATH/bin
。
要获取最新发布的版本:
GO111MODULE=on go get github.com/golang/mock/[email protected]
go install github.com/golang/mock/[email protected]
如果您在CI管道中使用mockgen
,则固定在特定的模拟器版本上可能更合适。您应该尝试使图书馆与用于生成模拟的模拟器的版本保持同步。
mockgen
具有两种操作模式:源和反射。
源模式从源文件生成模拟接口。使用-source标志启用它。在此模式下可能有用的其他标志是-Imports和-aux_files。
例子:
mockgen -source=foo.go [other options]
反射模式通过构建使用反射来理解接口的程序来生成模拟接口。通过传递两个非限制参数来启用它:导入路径和一个逗号分隔的符号列表。
您可以使用”。参考当前路径的软件包。
例子:
mockgen database/sql/driver Conn,Driver
# Convenient for `go:generate`.
mockgen . Conn,Driver
mockgen
命令用于生成一个模拟类的源代码,给定一个GO源文件,其中包含要模拟的接口。它支持以下标志:
-source
:包含要模拟的接口的文件。
-destination
:要编写生成的源代码的文件。如果您不设置此功能,则将代码打印到标准输出。
-package
:用于生成的模拟类源代码的软件包。如果您不设置此功能,则将软件包名称与输入文件的软件包mock_
。
-imports
:应在生成源代码中使用的明确导入列表,该源代码指定为逗号分隔的表单foo=bar/baz
的元素列表,其中bar/baz
是所导入的bar/baz,而foo
是标识符用于生成源代码中的软件包。
-aux_files
:应咨询其他文件以解决其他文件的列表,例如在另一个文件中定义的嵌入式接口。这被指定为表单foo=bar/baz.go
的逗号分隔列表,其中bar/baz.go
是源文件,而foo
是-source文件使用的该文件的包名称。
-build_flags
:(仅反映模式)标志逐字传递以go build
。
-mock_names
:生成模拟的自定义名称列表。这被指定为表单Repository=MockSensorRepository,Endpoint=MockSensorEndpoint
的逗号分隔的列表,其中Repository
是接口名称,而MockSensorRepository
是所需的模拟名称(模拟出厂方法和模拟录音机将在模拟之后命名)。如果其中一个接口未指定自定义名称,则将使用默认命名约定。
-self_package
:生成代码的完整软件包导入路径。该标志的目的是通过尝试包含自己的软件包来防止生成代码中的进口周期。如果将模拟的软件包设置为其输入之一(通常是主要的),并且输出为stdio,则可能会发生这种情况,因此Mockgen无法检测到最终的输出软件包。然后,设置此标志将告诉oikgen要排除哪个导入。
-copyright_file
:用于将版权标头添加到生成的源代码中的版权文件。
-debug_parser
:仅打印出解析器结果。
-exec_only
:(反射模式)如果设置,请执行此反射程序。
-prog_only
:(反射模式)仅生成反射程序;将其写入Stdout并退出。
-write_package_comment
:写包装文档评论(Godoc)如果为真的。 (默认为true)
有关使用mockgen
的示例,请参见sample/
目录。在简单的情况下,您只需要-source
标志。
type Foo interface {
Bar ( x int ) int
}
func SUT ( f Foo ) {
// ...
}
func TestFoo ( t * testing. T ) {
ctrl := gomock . NewController ( t )
// Assert that Bar() is invoked.
defer ctrl . Finish ()
m := NewMockFoo ( ctrl )
// Asserts that the first and only call to Bar() is passed 99.
// Anything else will fail.
m .
EXPECT ().
Bar ( gomock . Eq ( 99 )).
Return ( 101 )
SUT ( m )
}
如果您使用的是1.14+的GO版本,即1.5.0+的无知版本,并且正在将A *testing.t传递到gomock.NewController(t)
中,则不再需要明确调用ctrl.Finish()
。它将从自注册的清理功能自动为您服务。
type Foo interface {
Bar ( x int ) int
}
func SUT ( f Foo ) {
// ...
}
func TestFoo ( t * testing. T ) {
ctrl := gomock . NewController ( t )
defer ctrl . Finish ()
m := NewMockFoo ( ctrl )
// Does not make any assertions. Executes the anonymous functions and returns
// its result when Bar is invoked with 99.
m .
EXPECT ().
Bar ( gomock . Eq ( 99 )).
DoAndReturn ( func ( _ int ) int {
time . Sleep ( 1 * time . Second )
return 101
}).
AnyTimes ()
// Does not make any assertions. Returns 103 when Bar is invoked with 101.
m .
EXPECT ().
Bar ( gomock . Eq ( 101 )).
Return ( 103 ).
AnyTimes ()
SUT ( m )
}
当匹配器报告故障时,它会打印接收( Got
)与预期( Want
)值。
Got: [3]
Want: is equal to 2
Expected call at user_test.go:33 doesn ' t match the argument at index 1.
Got: [0 1 1 2 3]
Want: is equal to 1
Want
Want
值来自Matcher's String()
方法。如果匹配器的默认输出无法满足您的需求,则可以对其进行修改如下:
gomock . WantFormatter (
gomock . StringerFunc ( func () string { return "is equal to fifteen" }),
gomock . Eq ( 15 ),
)
这会修改gomock.Eq(15)
匹配器的输出Want:
从is equal to 15
is equal to fifteen
。
Got
如果可用,则Got
值来自对象的String()
方法。在某些情况下,对象的输出很难读取(例如, []byte
),对于测试以不同的方式打印它将很有帮助。以下修改了Got
值的格式:
gomock . GotFormatterAdapter (
gomock . GotFormatterFunc ( func ( i interface {}) string {
// Leading 0s
return fmt . Sprintf ( "%02d" , i )
}),
gomock . Eq ( 15 ),
)
如果收到的值为3
,则将其打印为03
。
cannot find package "."
... github.com/golang/mock/mockgen/model
如果在使用反射模式和供应依赖项时遇到此错误,则可以选择三个解决方法:
import _ "github.com/golang/mock/mockgen/model"
。--build_flags=--mod=mod
to to your oikgen命令。此错误是由于go
命令在最新版本中的默认行为的变化引起的。更多详细信息可以在#494中找到。