Created
December 10, 2018 23:50
-
-
Save ianfoo/fc7e37b837de883159a258581785e71f to your computer and use it in GitHub Desktop.
Gomock matcher for a set of arguments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package matchers | |
| import ( | |
| "fmt" | |
| "reflect" | |
| ) | |
| // SetMatcher matches values from a set of options. When an option is matched, | |
| // it is removed from the set of acceptable options and will not be matched | |
| // again on following calls to Match. This matcher can be useful when a number | |
| // of calls will be made with specific arguments, but the order is not known, | |
| // and a minimum and/or maximum number needs to be set. | |
| // | |
| // For example, given a set of three concurrent calls, where the arguments for | |
| // each call are known and different for at least one of the calls, and it is | |
| // known that at least one call will be made, but not known how many will end | |
| // up called (e.g., the first call triggers an error that should cancel | |
| // processing, but more calls may have been made before the cancellation). | |
| // Without this matcher, a test writer can either match arguments explicitly | |
| // but not test for the number of invocations: | |
| // | |
| // mocked.EXPECT().Method("arg1").AnyTimes() | |
| // mocked.EXPECT().Method("arg2").AnyTimes() | |
| // mocked.EXPECT().Method("arg3").AnyTimes() | |
| // | |
| // or can test for the number of invocations, but not the arguments: | |
| // | |
| // mocked.EXPECT().Method(gomock.Any()).MaxTimes(1).MinTimes(3) | |
| // | |
| // With SetMatcher, both can be tested: | |
| // | |
| // mocked.EXPECT().Method(NewSetMatcher("arg1", "arg2", "arg3")).MaxTimes(3).MinTimes(1) | |
| type SetMatcher struct { | |
| args []interface{} | |
| } | |
| // NewSetMatcher creates a new SetMatcher. | |
| func NewSetMatcher(args ...interface{}) *SetMatcher { | |
| return &SetMatcher{args: args} | |
| } | |
| // Matches implements https://godoc.org/github.com/golang/mock/gomock#Matcher | |
| // Matches method. | |
| func (sm *SetMatcher) Matches(x interface{}) bool { | |
| for i, y := range sm.args { | |
| if reflect.DeepEqual(x, y) { | |
| sm.args = append(sm.args[:i], sm.args[i+1:]...) | |
| return true | |
| } | |
| } | |
| return false | |
| } | |
| // String implements https://godoc.org/github.com/golang/mock/gomock#Matcher | |
| // String method. | |
| func (sm SetMatcher) String() string { | |
| switch len(sm.args) { | |
| case 0: | |
| return "<no possible match>" | |
| case 1: | |
| return fmt.Sprintf("%v", sm.args[0]) | |
| default: | |
| return fmt.Sprintf("any of %v", sm.args) | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment