Skip to content

An example go library that uses go.uber.org/mock to easily mock an external service for unit testing.

Notifications You must be signed in to change notification settings

peterjamesmatthews/go-mock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go Mock

An example go library that uses go.uber.org/mock to easily mock an external service for unit testing.

An important Application method CoolAlgorithm needs to be unit tested.

func (application *Application) CoolAlgorithm(input int) int {

CoolAlgorithm relies on an external calculator service and for whatever reason, that external service cannot be used during unit testing.

To remedy this, we first define the Calculatorer interface:

type Calculatorer interface {
// Add returns the sum of two ints.
Add(int, int) int
// Subtract returns the difference of two ints.
Subtract(int, int) int
// Multiply returns the product of two ints.
Multiply(int, int) int
// Divide returns the quotient of two ints.
Divide(int, int) int
}

In order to mock this interface, we first have to install mockgen:

go install go.uber.org/mock/mockgen@latest

We then use mockgen to generate a mock client to use in our unit test:

mockgen -source=./calculator/Calculatorer.go -destination=./mock_calculator/Client.go

// Code generated by MockGen. DO NOT EDIT.
// Source: ./calculator/Calculatorer.go
//
// Generated by this command:
//
// mockgen -source=./calculator/Calculatorer.go -destination=./mock_calculator/Client.go
//
// Package mock_calculator is a generated GoMock package.
package mock_calculator
import (
reflect "reflect"
gomock "go.uber.org/mock/gomock"
)
// MockCalculatorer is a mock of Calculatorer interface.
type MockCalculatorer struct {
ctrl *gomock.Controller
recorder *MockCalculatorerMockRecorder
}
// MockCalculatorerMockRecorder is the mock recorder for MockCalculatorer.
type MockCalculatorerMockRecorder struct {
mock *MockCalculatorer
}
// NewMockCalculatorer creates a new mock instance.
func NewMockCalculatorer(ctrl *gomock.Controller) *MockCalculatorer {
mock := &MockCalculatorer{ctrl: ctrl}
mock.recorder = &MockCalculatorerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockCalculatorer) EXPECT() *MockCalculatorerMockRecorder {
return m.recorder
}
// Add mocks base method.
func (m *MockCalculatorer) Add(arg0, arg1 int) int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Add", arg0, arg1)
ret0, _ := ret[0].(int)
return ret0
}
// Add indicates an expected call of Add.
func (mr *MockCalculatorerMockRecorder) Add(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockCalculatorer)(nil).Add), arg0, arg1)
}
// Divide mocks base method.
func (m *MockCalculatorer) Divide(arg0, arg1 int) int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Divide", arg0, arg1)
ret0, _ := ret[0].(int)
return ret0
}
// Divide indicates an expected call of Divide.
func (mr *MockCalculatorerMockRecorder) Divide(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Divide", reflect.TypeOf((*MockCalculatorer)(nil).Divide), arg0, arg1)
}
// Multiply mocks base method.
func (m *MockCalculatorer) Multiply(arg0, arg1 int) int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Multiply", arg0, arg1)
ret0, _ := ret[0].(int)
return ret0
}
// Multiply indicates an expected call of Multiply.
func (mr *MockCalculatorerMockRecorder) Multiply(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Multiply", reflect.TypeOf((*MockCalculatorer)(nil).Multiply), arg0, arg1)
}
// Subtract mocks base method.
func (m *MockCalculatorer) Subtract(arg0, arg1 int) int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Subtract", arg0, arg1)
ret0, _ := ret[0].(int)
return ret0
}
// Subtract indicates an expected call of Subtract.
func (mr *MockCalculatorerMockRecorder) Subtract(arg0, arg1 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subtract", reflect.TypeOf((*MockCalculatorer)(nil).Subtract), arg0, arg1)
}

Finally, we construct an Application instance that uses our mocked client. We set expectations and return values for the methods that will be called during the CoolAlgorithm unit test:

func TestCoolAlgorithm(t *testing.T) {
ctrl := gomock.NewController(t)
mockCalculator := mock_calculator.NewMockCalculatorer(ctrl)
application := application.Application{Calculator: mockCalculator}
number := 100
mockCalculator.
EXPECT().
Add(number, 0).
Times(1).
Return(number)
mockCalculator.
EXPECT().
Subtract(number, 0).
Times(1).
Return(number)
mockCalculator.
EXPECT().
Multiply(number, 1).
Times(1).
Return(number)
mockCalculator.
EXPECT().
Divide(number, 1).
Times(1).
Return(number)
if application.CoolAlgorithm(number) != number {
t.Fail()
}
}

About

An example go library that uses go.uber.org/mock to easily mock an external service for unit testing.

Topics

Resources

Stars

Watchers

Forks

Languages