unit-testinggomockingtestify

How to assert a partial match with stretchr/testify/mock AssertCalled?


Consider this unit test file in Go. I'm using github.com/stretchr/testify/mock package.

type Person struct {Name string; Age int}
type Doer struct { mock.Mock }

func (d *Doer) doWithThing(arg Person) {
    fmt.Printf("doWithThing %v\n", arg)
    d.Called(arg)
}

func TestDoer(t *testing.T) {
    d := new(Doer)
    d.On("doWithThing", mock.Anything).Return()
    d.doWithThing(Person{Name: "John", Age: 7})
    
    // I don't care what Age was passed. Only Name
    d.AssertCalled(t, "doWithThing", Person{Name: "John"})
}

This tests fails because testify uses Age: 0 in the comparison when I don't pass an age. I get that, but I'm wondering, how do I assert against a partial of the argument that was passed? I want this test to pass whatever Age is, so long as Name = John


Solution

  • Use mock.MatchedBy.

    In short, it wraps an arbitrary matcher function with a mock.argumentMatcher (unexported):

    argumentMatcher performs custom argument matching, returning whether or not the argument is matched by the expectation fixture function.

    In particular, the argument of mock.MatchedBy is:

    [...] a function accepting a single argument (of the expected type) which returns a bool

    So you can use it as follows:

    personNameMatcher := mock.MatchedBy(func(p Person) bool {
        return p.Name == "John"
    })
    d.AssertCalled(t, "doWithThing", personNameMatcher)