Skip to content

Commit

Permalink
feat: add Cond matcher (#60)
Browse files Browse the repository at this point in the history
This adds `Cond`, a new `Matcher` that can match using an arbitrary function.
If the function returns true for the parameter to the mock,
then there's a match.
  • Loading branch information
damianopetrungaro authored Aug 16, 2023
1 parent ffb768a commit 665220d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
22 changes: 22 additions & 0 deletions gomock/matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ func (anyMatcher) String() string {
return "is anything"
}

type condMatcher struct {
fn func(x any) bool
}

func (c condMatcher) Matches(x any) bool {
return c.fn(x)
}

func (condMatcher) String() string {
return "adheres to a custom condition"
}

type eqMatcher struct {
x any
}
Expand Down Expand Up @@ -280,6 +292,16 @@ func All(ms ...Matcher) Matcher { return allMatcher{ms} }
// Any returns a matcher that always matches.
func Any() Matcher { return anyMatcher{} }

// Cond returns a matcher that matches when the given function returns true
// after passing it the parameter to the mock function.
// This is particularly useful in case you want to match over a field of a custom struct, or dynamic logic.
//
// Example usage:
//
// Cond(func(x any){return x.(int) == 1}).Matches(1) // returns true
// Cond(func(x any){return x.(int) == 2}).Matches(1) // returns false
func Cond(fn func(x any) bool) Matcher { return condMatcher{fn} }

// Eq returns a matcher that matches on equality.
//
// Example usage:
Expand Down
4 changes: 4 additions & 0 deletions gomock/matchers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import (
)

type A []string
type B struct {
Name string
}

func TestMatchers(t *testing.T) {
type e any
Expand All @@ -50,6 +53,7 @@ func TestMatchers(t *testing.T) {
[]e{[]string{"a", "b"}, A{"a", "b"}},
[]e{[]string{"a"}, A{"b"}},
},
{"test Cond", gomock.Cond(func(x any) bool { return x.(B).Name == "Dam" }), []e{B{Name: "Dam"}}, []e{B{Name: "Dave"}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
4 changes: 3 additions & 1 deletion sample/imp4/imp4.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package imp_four

type Imp4 struct{}
type Imp4 struct {
Field string
}
17 changes: 17 additions & 0 deletions sample/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"go.uber.org/mock/gomock"
user "go.uber.org/mock/sample"
"go.uber.org/mock/sample/imp1"
imp_four "go.uber.org/mock/sample/imp4"
)

func TestRemember(t *testing.T) {
Expand Down Expand Up @@ -193,3 +194,19 @@ func TestDoAndReturnSignature(t *testing.T) {
mockIndex.Slice([]int{0}, []byte("meow"))
})
}

func TestExpectCondForeignFour(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockIndex := NewMockIndex(ctrl)
mockIndex.EXPECT().ForeignFour(gomock.Cond(func(x any) bool {
four, ok := x.(imp_four.Imp4)
if !ok {
return false
}
return four.Field == "Cool"
}))

mockIndex.ForeignFour(imp_four.Imp4{Field: "Cool"})
}

0 comments on commit 665220d

Please sign in to comment.