更新,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中找到。