uber-go/mock

GitHub: uber-go/mock

Uber 维护的 Go 语言 mocking 框架,通过 mockgen 自动从接口生成 mock 代码以简化单元测试。

Stars: 3386 | Forks: 173

# gomock [![Build Status](https://static.pigsec.cn/wp-content/uploads/repos/cas/79/79613cf8ba5572c68aaf28354024c64bc093ff7b7db74cae9e5920034527c7c5.svg)][ci-runs] [![Go Reference](https://pkg.go.dev/badge/go.uber.org/mock.svg)][reference] gomock 是一个用于 [Go 编程语言][golang] 的 mocking 框架。它 与 Go 的内置 `testing` 包集成良好,但也可以在其他 环境中使用。 该项目起源于 Google 的 `golang/mock` 仓库。遗憾的是,Google 不再维护此项目,并且鉴于 gomock 在 Uber 内部的广泛使用, 我们决定 fork 该项目,并在 Uber 继续对其进行维护。 ## 支持的 Go 版本 go.uber.org/mock 支持官方 [Go 发布策略](https://go.dev/doc/devel/release#policy) 所支持的所有 Go 版本。即, Go 的两个最新发布版本。 ## 安装 安装 `mockgen` 工具。 ``` go install go.uber.org/mock/mockgen@latest ``` 要确保其安装正确,请使用: ``` mockgen -version ``` 如果失败,请确保您的 GOPATH/bin 已包含在 PATH 中。您可以通过以下命令添加: ``` export PATH=$PATH:$(go env GOPATH)/bin ``` ## 运行 mockgen `mockgen` 有三种操作模式:archive、source 和 package。 ### Archive 模式 Archive 模式从一个包归档 文件 (.a) 生成 mock 接口。通过使用 -archive 标志来启用。应提供一个导入 路径和一个以逗号分隔的符号列表,作为该命令的非标志参数。 示例: ``` # 将 package 构建为 archive。 go build -o pkg.a database/sql/driver mockgen -archive=pkg.a database/sql/driver Conn,Driver ``` ### Source 模式 Source 模式从一个源文件生成 mock 接口。 通过使用 -source 标志来启用。在此模式下,其他可能 有用的标志包括 -imports 和 -aux_files。 示例: ``` mockgen -source=foo.go [other options] ``` ### Package 模式 Package 模式通过指定包名和接口名来工作。 通过传递两个非标志参数来启用:一个导入路径,以及一个 以逗号分隔的符号列表。 您可以使用 "." 来引用当前路径的包。 示例: ``` mockgen database/sql/driver Conn,Driver # 便于在 `go:generate` 中使用。 mockgen . Conn,Driver ``` ### 标志 `mockgen` 命令用于在给定一个包含需要 mock 的接口的 Go 源文件的情况下, 为 mock 类生成源代码。 它支持以下标志: - `-archive`:一个包含需要 mock 的接口的包归档文件。 - `-source`:一个包含需要 mock 的接口的文件。 - `-destination`:用于写入生成的源代码的文件。如果您 没有设置此项,代码将打印到标准输出。 - `-package`:用于生成的 mock 类 源代码的包。如果您没有设置此项,包名将为 `mock_` 并 拼接上输入文件的包名。 - `-imports`:在生成的 源代码中应使用的显式导入列表,指定为以逗号分隔的元素列表, 格式为 `foo=bar/baz`,其中 `bar/baz` 是被导入的包,而 `foo` 是 在生成的源代码中用于该包的标识符。 - `-aux_files`:为了解析(例如,定义在不同文件中的嵌入接口)而需要参考的 附加文件列表。这 指定为以逗号分隔的元素列表,格式为 `foo=bar/baz.go`,其中 `bar/baz.go` 是源文件,而 `foo` 是 -source 文件所使用的该文件的包名。 - `-build_flags`:(仅限 package 模式)原样传递给 `go list` 的标志。 - `-mock_names`:生成的 mock 的自定义名称列表。这 指定为以逗号分隔的元素列表,格式为 `Repository=MockSensorRepository,Endpoint=MockSensorEndpoint`,其中 `Repository` 是接口名,而 `MockSensorRepository` 是所需的 mock 名称(mock 工厂方法和 mock 记录器将以该 mock 命名)。 如果其中一个接口没有指定自定义名称,则将使用默认的命名 约定。 - `-self_package`:生成代码的完整包导入路径。此 标志的目的是防止在生成代码时,因尝试包含其自身的包而导致 导入循环。这种情况可能发生在 mock 的包 被设置为其输入之一(通常是主要的那个)且输出为 stdio 时,因此 mockgen 无法检测到最终的输出包。设置此标志将 告诉 mockgen 要排除哪个导入。 - `-copyright_file`:用于向生成的源代码添加版权头的版权文件。 - `-debug_parser`:仅打印解析器结果。 - `-write_package_comment`:如果为 true,则写入包文档注释 (godoc)。(默认为 true) - `-write_generate_directive`:添加 //go:generate 指令以重新生成 mock。(默认为 false) - `-write_source_comment`:如果为 true,则写入原始文件(source 模式)或接口名(package 模式)注释。(默认为 true) - `-typed`:生成类型安全的 'Return'、'Do'、'DoAndReturn' 函数。(默认为 false) - `-exclude_interfaces`:要排除的接口名称,以逗号分隔 有关 `mockgen` 用法的示例,请参见 `sample/` 目录。在简单的 情况下,您将只需要 `-source` 标志。 ## 构建 Mock ``` type Foo interface { Bar(x int) int } func SUT(f Foo) { // ... } ``` ``` func TestFoo(t *testing.T) { ctrl := gomock.NewController(t) 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) } ``` ## 构建 Stub ``` type Foo interface { Bar(x int) int } func SUT(f Foo) { // ... } ``` ``` func TestFoo(t *testing.T) { ctrl := gomock.NewController(t) 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) } ``` ## 修改失败信息 当 matcher 报告失败时,它会打印接收到的(`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 的 `String()` 方法。如果 matcher 的 默认输出不能满足您的需求,可以按如下方式进行修改: ``` gomock.WantFormatter( gomock.StringerFunc(func() string { return "is equal to fifteen" }), gomock.Eq(15), ) ``` 这会将 `gomock.Eq(15)` matcher 针对于 `Want:` 的输出从 `is equal to 15` 修改为 `is equal to fifteen`。 ### 修改 `Got` `Got` 值来自对象的 `String()` 方法(如果可用)。 在某些情况下,对象的输出难以阅读(例如,`[]byte`), 如果测试能以不同的方式打印它会很有帮助。以下内容 修改了 `Got` 值的格式化方式: ``` gomock.GotFormatterAdapter( gomock.GotFormatterFunc(func(i any) string { // Leading 0s return fmt.Sprintf("%02d", i) }), gomock.Eq(15), ) ``` 如果接收到的值为 `3`,那么它将被打印为 `03`。
标签:EVTX分析, Go, Mock框架, Ruby工具, SOC Prime, 代码生成, 单元测试, 开发工具, 日志审计, 测试工具, 渗透测试工具