Cannot pass Testify Mock object error

MadzQuestioning picture MadzQuestioning · Jun 9, 2018 · Viewed 7.2k times · Source

Hi I'm trying to mock a struct in GO. I'm using testify to do this. But I can't seem to get it to work and don't now what I'm doing wrong. Below is the sample main.go and main_test.go file I have

// Arithmetic ...
type Arithmetic interface {
    Add(int, int) int
    Subtract(int, int) int
}

// MathOperation ...
type MathOperation struct {}

// GetNewArithmetic ...
func GetNewArithmetic(obj Arithmetic) Arithmetic {
    if obj != nil {
        return obj
    }

    return MathOperation{}
}

// Add ...
func (a MathOperation) Add(num1 int, num2 int) int {
    return num1 + num2
}

// Subtract ...
func (a MathOperation) Subtract(num1 int, num2 int) int {
    return num1 - num2
}

And here is my test file

import (
    "testing"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

type MyMock struct {
    mock.Mock
}

func (m *MyMock) Add(num1 int, num2 int) int {
    args := m.Called(num1, num2)
    return args.Int(0) + args.Int(1)
}

func (m *MyMock) Subtract(num1 int, num2 int) int {
    args := m.Called(num1, num2)
    return args.Int(0) + args.Int(1)
}

func TestDoComputation(t *testing.T) {
    testobj := new(MyMock)

    testobj.On("Add", 1, 2).Return(5)

    // a := GetNewArithmetic(testobj)

    result := GetNewArithmetic(testobj)

    assert.Equal(t, 5, result.Add(5, 6))
    testobj.AssertExpectations(t)
}

I receive this error

--- FAIL: TestDoComputation (0.00s)
panic:

mock: Unexpected Method Call
-----------------------------

Add(int,int)
            0: 5
            1: 6

The closest call I have is:

Add(int,int)
            0: 1
            1: 2


 [recovered]
        panic:

mock: Unexpected Method Call
-----------------------------

Add(int,int)
            0: 5
            1: 6

The closest call I have is:

Add(int,int)
            0: 1
            1: 2

goroutine 13 [running]:
testing.tRunner.func1(0xc420106870)
        /usr/lib/golang/src/testing/testing.go:711 +0x2d2
panic(0x701160, 0xc420011070)

I have no idea on how to fix since this is my first time using Go and using Testify to do unit testing. Would appreciate if someone can take a look and have a working version of this. Thanks

Answer

mkopriva picture mkopriva · Jun 9, 2018

The line

testobj.On("Add", 1, 2).Return(5)

means that you expect the testobj mock to receive a call to its Add method with arguments 1 and 2 passed to it, and you also specify that that call should return the integer value 5.

But instead on this line

assert.Equal(t, 5, result.Add(5, 6))

you are calling the method Add with arguments 5 and 6.

This results in the error you got:

mock: Unexpected Method Call
-----------------------------

Add(int,int)
            0: 5
            1: 6
// this is result.Add(5, 6), the 0: and 1: are indexes of the actually passed in aguments.

The closest call I have is:

Add(int,int)
            0: 1
            1: 2
// this is testobj.On("Add", 1, 2), and 0: and 1: are indexes of the expected arguments.

On top of that your mock implementations are attempting to calculate and return the value. This is not what a mock should do. A mock should instead return the value provided to it through the Return method.

The way you can do this is by using the args value returned from the Called method call, this value will hold the Return method's arguments indexed in the same order they were passed in to Return.

So the integer value 5 that you passed to Return on this line

testobj.On("Add", 1, 2).Return(5)

can be accessed using the Int utility method and passing it the 0th index. That is return args.Int(0) will return the interger value 5.

So your test file should look more like this:

import (
    "testing"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

type MyMock struct {
    mock.Mock
}

func (m *MyMock) Add(num1 int, num2 int) int {
    args := m.Called(num1, num2)
    return args.Int(0)
}

func (m *MyMock) Subtract(num1 int, num2 int) int {
    args := m.Called(num1, num2)
    return args.Int(0)
}

func TestDoComputation(t *testing.T) {
    testobj := new(MyMock)

    testobj.On("Add", 1, 2).Return(5)

    // a := GetNewArithmetic(testobj)

    result := GetNewArithmetic(testobj)

    assert.Equal(t, 5, result.Add(1, 2))
    testobj.AssertExpectations(t)
}