0

I am writing the following unit test:

type mockQux struct {
    mock.Mock
    MockInterface
    calculateHash      func(ctx context.Context, foo *entities.Foo, bar model.Bar, baz *model.Baz) (uint64, error)
}

type MockInterface interface {
    On(methodName string, arguments ...interface{}) *mock.Call
    AssertExpectations func(t mock.TestingT)
}

func (m *mockQux) TestCalculateHash(t *testing.T) {
mq := new(mockQux)
ctx := context.Background()
    foo := &entities.Foo{
    // foo's fields
}
// create instances of model.Bar and &model.Baz the same way I created foo variable
mq.On("calculateHash", ctx, foo, bar, baz).Return(uint64(123), nil)

hash, err := m.Mock.calculateHash(ctx, foo, bar, baz)

assert.Equal(t, uint64(123), hash)
    assert.Nil(t, err)

    m.Mock.AssertExpectations(t)
}

func TestCalculateHash(t *testing.T) {
    m := new(mockQux)
    m.TestCalculateHash(t)
}

Running go test and go test -c, why do I get a segfault on On and AssertExpectations?

I've tried debugging this with delve, but it crashes whenever I run it, even if I instruct it to step over the problematic lines. I guess the problem might be that I improperly reference the variables in arguments to mq.On or that I don't initialize all the fields (these structs are pretty complex).

olithad
  • 50
  • 4
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Feb 03 '23 at 05:00

1 Answers1

0

There are too many fail point in your code sample to tell what's the exact root cause of the segfault. That's generally not how testify mock are used. You don't need either your MockInterface definition. Also you cannot have a segfault on 2 different locations, your program either segfault on On or AssertExpectations. That cannot be both. I strongly suspect though that your segfault come from this call:

hash, err := m.Mock.calculateHash(ctx, foo, bar, baz)

as this function pointer from your struct does not seem to be initialized.

About how to use mock in testify, we usually do something like that. Here is a minimal nominal code without any business logic:

type ConcreteType struct {}
func (m *ConcreteType) DoSomething() int { return 3 }

type DoSomethinger interface {
    DoSomething() int
}

func UseConcreteType(s DoSomethinger) error {
   if val := s.DoSomething(); val != 3 {
       return fmt.Errorf("unexpected value: %d", val)
   }
}

In your test you would do something like that:

type DoSomethingMock struct {
    mock.Mock
}

func (m *DoSomethingMock) DoSomething() int {
    args := m.Called()
    return args.Int(0)
}

func TestUseConcrete(t *testing.T) {
   m := &DoSomethingMock{}
   m.On("DoSomething").Return(4)
   err := UseConcreteType(m)
   require.Error(t, err)
}
davidriod
  • 937
  • 5
  • 14