6

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

blackgreen
  • 34,072
  • 23
  • 111
  • 129
BeetleJuice
  • 39,516
  • 19
  • 105
  • 165

1 Answers1

11

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)
blackgreen
  • 34,072
  • 23
  • 111
  • 129