Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”
This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money
At work, many companies demand efficiency and automated testing
When you’re actually in the ground, it turns out that you’re going to do unit testing, automated testing, maybe the current service is going to rely on other services’ data, interfaces, etc
During the single test or automation process, the test may fail or block due to other services or environmental factors
This is a problem that has to be solved, and we can use golang’s built-in mock tool to do this. We can pile data where necessary, mock data
What’s a gomock?
Mock data is an official provided framework for mock data
The Mockgen tool was also provided to help us generate test code
The project address on Github is github.com/golang/mock
Here’s how gomock is officially introduced:
Gomock is a mocking framework for the Go programming language. It integrates well with Go’s built-in test suite, but can also be used in other environments.
How do I use Gomock?
Gomock is also very easy to use, starting with go get the corresponding tools gomock and Mockgen
go get -u github.com/golang/mock/gomock
go get -u github.com/golang/mock/mockgen
Copy the code
You can write a demo to do this
The directory structure looks like this
├── Go, do, do, do, do, do, do, do, do, do, do, do, do, do, do, do, do, do, do, do myuser_test.goCopy the code
- Mock_myfunc.go is generated using the Mockgen tool
- Myfunc.go is mainly used to simulate the underlying implementation of the call
- Myuser. go basically calls the interface inside myfunc. Go
- Myuser_test. go is the corresponding single test file
myfunc.go
- Write an interface that has a
GetInfo() string
Method, simulation to obtain information
package myfunc
type MyFunc interface {
GetInfo() string
}
Copy the code
myuser.go
- Call the method in myfunc.go and call the interface to get the information
package myfunc
func getUser(m MyFunc) string {
user := m.GetInfo()
return user
}
Copy the code
Mock file generation
mock_myfunc.go
We did not write this file ourselves, but generated it using the Mockgen tool as follows:
Execute the following statement in the parent directory of myfunc.go to generate the mock file by filling in the source source and target files
mockgen -source=myfunc.go -destination=mock_myfunc.go
Copy the code
Take a look at the Mockgen help, and there are other parameters you can use
# mockgenmockgen has two modes of operation: source and reflect. Source mode generates mock interfaces from a source file. It is enabled by using the -source flag. Other flags that may be useful in this mode are -imports and -aux_files. Example: mockgen -source=foo.go [other options] Reflect mode generates mock interfaces by building a program that uses reflection to understand interfaces. It is enabled by passing two non-flag arguments: an import path, and a comma-separated list of symbols. Example: mockgen database/sql/driver Conn,Driver -aux_files string (source mode) Comma-separated pkg=path pairs of auxiliary Go source files. -build_flags string (reflect mode) Additional flags for go build. -copyright_file string Copyright file used to add copyright header -debug_parser Print out parser results only. -destination string Output file; defaults to stdout. -exec_only string (reflect mode) If set, execute this reflection program. -imports string (source mode) Comma-separated name=path pairs of explicit imports to use. -mock_names string Comma-separated interfaceName=mockName pairs of explicit mock names to use. Mock names default to 'Mock'+ interfaceName suffix. -package string Package of the generated code; defaults to the package of the input with a 'mock_' prefix. -prog_only (reflect mode) Only generate the reflection program; write it to stdout and exit. -self_package string The full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. This can happen if the mock's package is set to one of its inputs (usually the main one) and the output is stdio so mockgen cannot detect the final output package. Setting this flag will then tell mockgen which import to exclude. -source string (source mode) Input Go source file; enables source mode. -version Print version. -write_package_comment Writes package documentation comment (godoc) if true. (default true) 2021/10/30 16:43:25 Expected exactly two argumentsCopy the code
In general, it is more commonly used
-source
The source file-destination
The target file-imports
Dependent packages that need to be imported-build_flags
Parameters passed to the build tool-aux_files
The interface file is appended if there is more than one file-package
Set the package name of the mock file. If this is not set, the package name of the mock file defaults toMock_ Enter the package name of the file
The mock file generated from the above instruction looks like this:
- NewMockMyFunc
Create a new mock instance
- EXPECT
An object that allows the caller to indicate the intended use
- GetInfo
The basic method of the mock, which is the method we need to mock
How to use it
myuser_test.go
- The single test file corresponding to myUser. go uses the mock method
package myfunc
import (
"fmt"
"testing"
gomock "github.com/golang/mock/gomock"
)
func Test_getUser(t *testing.T) {
mockCtl := gomock.NewController(t)
mockMyFunc := NewMockMyFunc(mockCtl)
mockMyFunc.EXPECT().GetInfo().Return("xiaomotong")
v := getUser(mockMyFunc)
if v == "xiaomotong" {
fmt.Println("get user right!")}else {
t.Error("get error user")}}Copy the code
If you don’t know the difference, let’s look at how to write a single test without a mock
package myfunc
import (
"fmt"
"testing"
gomock "github.com/golang/mock/gomock"
)
func Test_getUser(t *testing.T) {
m := myfunc.CreateMyFunc() // Create your own object
v := getUser(m)
if v == "xiaomotong" {
fmt.Println("get user right!")}else {
t.Error("get error user")}}Copy the code
M := myfunc.CreateMyFunc() = myfunc.CreateMyFunc() = myfunc
However, creating MyFunc objects at this point is not yet coded due to external dependencies, but it does not block our unit tests
You can mock a MyFunc object and set the return value to mock it. For example:
mockCtl := gomock.NewController(t)
mockMyFunc := NewMockMyFunc(mockCtl)
mockMyFunc.EXPECT().GetInfo().Return("xiaomotong")
Copy the code
The result of executing the above code is as follows:
> go testget user right! PASS ok mygomock/myfunc is 0.427 sCopy the code
Interested friends can use it, use more will be more familiar with
What are the benefits of gomock?
- Gomock implements a fairly complete interface-based Mock feature that integrates well with Golang’s built-in Testing package and can be used in other testing environments
- It’s cheap and easy to learn
Tools need to be used, to play its value, need to use it
Welcome to like, follow and favorites
Friends, your support and encouragement, I insist on sharing, improve the quality of the power
All right, that’s it for this time
Common technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.
I am Nezha, welcome to like, see you next time ~