Getting Started #
In this article we are going to learn how to use GoMock to generate mock implementations of interface
s in Go.
Installing GoMock #
GoMock works as a command line application to generate mocked source code, but you also have to install it in your application to use the generated mock code.
Installing the cli tool:
go install github.com/golang/mock/[email protected]
Installing gomock in your go project:
go get github.com/golang/mock/gomock
Generating mock code #
Let's say we have the following code in your main.go
file.
package main
// š an interface acting as API Client
type ApiClient interface {
GetData() string
}
// š a function using the ApiClient interface
func Process(client ApiClient) int {
data := client.GetData()
return len(data)
}
func main() {
}
In the above piece of code we have an interface ApiClient
that is being used by the Process
function. Lets say we want to test the Process
function and we require a mock implementation of ApiClient
when doing so.
To generate mock implementation of ApiClient
run the following code in the project root:
mockgen -source=main.go -destination=mocks/main.go
This will generate a mock implementation of the interfaace ApiClient
and write the code into mocks/main.go
file.
We don't really care about the generated code but here is the generated code to satisfy your curiosity (don't bother to understand it, just glance over it).
// Code generated by MockGen. DO NOT EDIT.
// Source: main.go
// Package mock_main is a generated GoMock package.
package mock_main
import (
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockApiClient is a mock of ApiClient interface.
type MockApiClient struct {
ctrl *gomock.Controller
recorder *MockApiClientMockRecorder
}
// MockApiClientMockRecorder is the mock recorder for MockApiClient.
type MockApiClientMockRecorder struct {
mock *MockApiClient
}
// NewMockApiClient creates a new mock instance.
func NewMockApiClient(ctrl *gomock.Controller) *MockApiClient {
mock := &MockApiClient{ctrl: ctrl}
mock.recorder = &MockApiClientMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockApiClient) EXPECT() *MockApiClientMockRecorder {
return m.recorder
}
// GetData mocks base method.
func (m *MockApiClient) GetData() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetData")
ret0, _ := ret[0].(string)
return ret0
}
// GetData indicates an expected call of GetData.
func (mr *MockApiClientMockRecorder) GetData() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetData", reflect.TypeOf((*MockApiClient)(nil).GetData))
}
Look closely we have an struct called MockApiClient
that has all the functions of ApiClient
(GetData
in this case). Additionally we have a function called NewMockApiClient
that we can use to get an instance of MockApiClient
in our tests.
Using the mock code #
Create a new file called mock_test.go
and add the following code:
package main
import (
"github.com/golang/mock/gomock"
mock_main "github.com/gurleensethi/playground/mocks"
"testing"
)
func TestProcess(t *testing.T) {
ctrl := gomock.NewController(t)
// š create new mock client
mockApiClient := mock_main.NewMockApiClient(ctrl)
// š configure our mock `GetData` function to return mock data
mockApiClient.EXPECT().GetData().Return("Hello World")
length := Process(mockApiClient)
if length != 11 {
t.Fatalf("want: %d, got: %d\n", 11, length)
}
}
We use the NewMockApiClient
function to get an instance that we can use wherever ApiClient
interface is expected.
mockApiClient := mock_main.NewMockApiClient(ctrl)
Pay attention to how we configure the GetData
function on the mock client to return the data that we want.
mockApiClient.EXPECT().GetData().Return("Hello World")
Check out GoMock documentation it has a lot more options to configure mocks, it has a reflection mode which allows you to generate mocks of interfaces from packages that you have not written yourself and much more.
Thank your for reading this article šš» hopefully you learned something new.