With mocked implementation of the interface, you can provide mocked data to satisfy your tests. In the example below, CountRows needs a service, which we injected with the mocked version in the unit test. For the mock to work, we should set an expectation by using .On(). With each test case, we set a different return argument depending on the requirement of the test.
mockSvc := servicemock.NewService(t)
mockSvc.On("GetRows", ctx).Return(tt.rows, nil)
main.go
//go:generate mockery --name=Service --dir=. --output=./mocks --outpkg=servicemock --case=snake
// ...
type Service interface {
GetRows(ctx context.Context) ([]any, error)
}
func CountRows(ctx context.Context, svc Service) (int, error) {
rows, err := svc.GetRows(ctx)
if err != nil {
return 0, err
}
return len(rows), nil
}
main_test.go
func TestCountRows(t *testing.T) {
ctx := context.Background()
tests := []struct {
name string
rows []any
want int
}{
{name: "empty", rows: nil, want: 0},
{name: "three", rows: []any{"a", "b", "c"}, want: 3},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockSvc := servicemock.NewService(t)
mockSvc.On("GetRows", ctx).Return(tt.rows, nil)
got, err := CountRows(ctx, mockSvc)
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
Mocked service below:
// Code generated by mockery v2.53.5. DO NOT EDIT.
package servicemock
import (
context "context"
mock "github.com/stretchr/testify/mock"
)
// Service is an autogenerated mock type for the Service type
type Service struct {
mock.Mock
}
// GetRows provides a mock function with given fields: ctx
func (_m *Service) GetRows(ctx context.Context) ([]interface{}, error) {
ret := _m.Called(ctx)
if len(ret) == 0 {
panic("no return value specified for GetRows")
}
var r0 []interface{}
var r1 error
if rf, ok := ret.Get(0).(func(context.Context) ([]interface{}, error)); ok {
return rf(ctx)
}
if rf, ok := ret.Get(0).(func(context.Context) []interface{}); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]interface{})
}
}
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewService(t interface {
mock.TestingT
Cleanup(func())
}) *Service {
mock := &Service{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}