golang / mock

GoMock is a mocking framework for the Go programming language.
Apache License 2.0
9.26k stars 608 forks source link

Unable to use goMock to test further logic in service implementation #699

Closed inianv closed 1 year ago

inianv commented 1 year ago

I have a rough implementation of a service whose structure looks like this simplified example. Basically a logic defined by this interface Logic is provided by a LogicProvider, so that an example provider like ExampleLogicProvider can implement the methods needed to provide service.

package main

type LogicProvider struct {
    Logic Logic
}

type Logic interface {
    AFunction() error
    BFunction() error
}

type ExampleLogicProvider struct{}

func (lp *ExampleLogicProvider) AFunction() error {
    // more behavior and logic available here, which need to be tested
    return nil
}

func (lp *ExampleLogicProvider) BFunction() error {
    // more behavior and logic available here, which need to be tested
    return nil
}

func (lp *LogicProvider) AFunction() error {
    return lp.Logic.AFunction()
}

func (lp *LogicProvider) BFunction() error {
    return lp.Logic.BFunction()
}

func NewClient() Logic {
    elp := &ExampleLogicProvider{}
    return &LogicProvider{Logic: elp}
}

func main() {
    var _ Logic = (&ExampleLogicProvider{})
}

When I try to use gomock to generate stubs for this, it is not possible to test the further behaviour defined in the example provider's AFunction and BFunction. The test code that I have is follows

func TestMockProvider(t *testing.T) {
    mockCtrl := gomock.NewController(t)
    defer mockCtrl.Finish()
    mockProvider := mocks.NewMockLogic(mockCtrl)
    testProvider := &main.LogicProvider{
        Logic: mockProvider,
    }

    mockProvider.EXPECT().AFunction().Return(errors.New("foobar"))
    err := testProvider.AFunction()
    if err != nil {
        t.Fatal(err)
    }
}

With the stub definition below, I am able to only control the mocked provider's implementation of AFunction() and making it immediately return back without actually invoking the actual logic provider's AFunction() i.e. lp.Logic.AFunction()

mockProvider.EXPECT().AFunction().Return(errors.New("foobar"))

There is a lot more logic and methods that I need to test out in the provider's AFunction() and BFunction(). I don't know if I need to redesign the interface design or something obvious that I'm unable to notice here.

Could someone point me in the right direction and give me some guidance? Any help would be much appreciated!


Generated mock code for reference

// Code generated by MockGen. DO NOT EDIT.
// Source: main.go

// Package mocks is a generated GoMock package.
package mocks

import (
    reflect "reflect"

    gomock "github.com/golang/mock/gomock"
)

// MockLogic is a mock of Logic interface.
type MockLogic struct {
    ctrl     *gomock.Controller
    recorder *MockLogicMockRecorder
}

// MockLogicMockRecorder is the mock recorder for MockLogic.
type MockLogicMockRecorder struct {
    mock *MockLogic
}

// NewMockLogic creates a new mock instance.
func NewMockLogic(ctrl *gomock.Controller) *MockLogic {
    mock := &MockLogic{ctrl: ctrl}
    mock.recorder = &MockLogicMockRecorder{mock}
    return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockLogic) EXPECT() *MockLogicMockRecorder {
    return m.recorder
}

// AFunction mocks base method.
func (m *MockLogic) AFunction() error {
    m.ctrl.T.Helper()
    ret := m.ctrl.Call(m, "AFunction")
    ret0, _ := ret[0].(error)
    return ret0
}

// AFunction indicates an expected call of AFunction.
func (mr *MockLogicMockRecorder) AFunction() *gomock.Call {
    mr.mock.ctrl.T.Helper()
    return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AFunction", reflect.TypeOf((*MockLogic)(nil).AFunction))
}

// BFunction mocks base method.
func (m *MockLogic) BFunction() error {
    m.ctrl.T.Helper()
    ret := m.ctrl.Call(m, "BFunction")
    ret0, _ := ret[0].(error)
    return ret0
}

// BFunction indicates an expected call of BFunction.
func (mr *MockLogicMockRecorder) BFunction() *gomock.Call {
    mr.mock.ctrl.T.Helper()
    return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BFunction", reflect.TypeOf((*MockLogic)(nil).BFunction))
}