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

1

12

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

Sagittate answered 12/7, 2021 at 15:17 Comment(0)
B
15

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)
Battat answered 12/7, 2021 at 16:52 Comment(2)
I just want to add that you can also use these in your expectations, e.g. d.On("doWithThing", personNameMatcher).Grewitz
For some reason it fails for me. It is comparing function to an object.Betti

© 2022 - 2024 — McMap. All rights reserved.