4

I'm using gin-gonic for a server, and testify for testing and mocks, along with "testing" and "net/http/httptest"

The part of the interface that mocks the method:

func (m *MockInterface) Method(ctx context.Context, id string, deleted bool) ([]models.Entity, error) {
    args := m.Called(ctx, id, deleted)

    var entities []models.Entity
    if args.Get(0) != nil {
        entities = args.Get(0).([]models.Entity)
    }

    var err error
    if args.Get(1) != nil {
        err = args.Error(1)
    }

    return entities, err
}

Setting it up in a test - the server is setup outside of this t.Run, there are tests before this that run fine.

    t.Run("TestName", func(t *testing.T) {
        mockInterface := new(mocks.MockInterface)

        mockInterface.On("Method", mock.AnythingOfType("*context.timerCtx"), id.String(), true).Return(mockResp, nil)

        // a response writer to capture the response
        rr := httptest.NewRecorder()

        url := "SomeURLString"
        // make the request to the Method handler
        request, err := http.NewRequest(http.MethodGet, url, nil)
        assert.NoError(t, err)

        router.ServeHTTP(rr, request)

        assert.NoError(t, err)
        assert.Equal(t, http.StatusOK, rr.Code)

        mockInterface.AssertExpectations(t)
    })

This is where it panics:

router.ServeHTTP(rr, request)
mock: Unexpected Method Call
-----------------------------

Method(*context.timerCtx,string,bool)
        0: &context.timerCtx{cancelCtx:context.cancelCtx{Context:(*context.emptyCtx)...etc}}
        1: "MatchingID"
        2: true

The closest call I have is: 

Method(mock.AnythingOfTypeArgument,string,bool)
        0: "*context.timerCtx"
        1: "MatchingID"
        2: false

When I go into debug mode, mockInterface.Mock.ExpectedCalls[0].Arguments[2] is true, just as I set it. And then it panics and says it's not... while it is still true!

I've gone far enough into the stack to verify that the handler called method with the boolean as true, so it ought to pass. Instead it panics, and I'm not sure where to go from here to figure out why.

Does anyone know what is going on here? Is there some kind of odd interaction between gin and testify that I'm missing? Thank you.

Laura
  • 288
  • 1
  • 4
  • 14
  • Did you call `mockInterface.On("Method"...` in previous test within the same package? – BlackLotus May 30 '22 at 14:01
  • Yes I did, but I also declared a new mockInterface for each test, so it shouldn't matter. And the matchingID, which is unique to this test, was the same for the expected and real call. This is still also my suspicion, but I don't see how its possible that it reused a previous mockInterface when I called for a new instance of one. – Laura Jun 01 '22 at 17:08
  • 1
    Then maybe `.Once()` method will work for you, just put it after every `.On()` method, this will make sure your mock only work once. i.e `mockInterface.On("Method", mock.AnythingOfType("*context.timerCtx"), id.String(), true).Once().Return(mockResp, nil)` – BlackLotus Jun 02 '22 at 18:17

0 Answers0