-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestions for matchers and matcher generation #110
Comments
Hi @yhrn, thanks for taking the time to open this issue. Let's look at the points one by one:
Overall, I think your comments make sense and I'm happy to help. My bandwidth for this project unfortunately is very limited these days, which is why I suggest to people to contribute in form of a PR. I'm happy to review that and merge it. I just can't make the changes myself. Thanks, |
Hi and thanks for the response!
As for your bandwidth that is very understandable and I'm happy to contribute. 1 & 2, if you think that 2 makes sense after my example below, feels like something that I can easily do. 3 & 4 might not be worth it and 5 is probably a bit too complex for me to find time to take on. I might create a separate issue for that one so that it is tracked cleanly at least. So the example for 2. I was trying to create an adapter for using Gomega matchers with Pegomock. It turns out that it's not a great fit anyway but it serves as a decent example and there might be some other third party matcher library that would work better. So if I have this code that could live in some reusable "test-util" style package: // Should returns a Pegomock matcher that delegates to a Gomega matcher.
func Should(gomegaMatcher gomegatypes.GomegaMatcher) pegomock.Matcher {
return &pegomegaMatcher{gomegaMatcher: gomegaMatcher}
}
// pegomegaMatcher is a suboptimal Gomega Pegomock adapter (with a great name).
type pegomegaMatcher struct {
gomegaMatcher gomegatypes.GomegaMatcher
failureMsg string
sync.Mutex
}
func (p *pegomegaMatcher) Matches(param pegomock.Param) bool {
p.Lock()
defer p.Unlock()
matches, err := p.gomegaMatcher.Match(param)
if err != nil {
p.failureMsg = err.Error()
return false
} else if !matches {
p.failureMsg = p.gomegaMatcher.FailureMessage(param)
return false
}
return true
}
func (p *pegomegaMatcher) FailureMessage() string {
return p.failureMsg
}
func (p *pegomegaMatcher) String() string {
// Obviously not great
return p.gomegaMatcher.FailureMessage("arg")
} I could then use it like this: // This struct is not test code but included in the example to make things a bit more obvious
type Request struct {
MyString string
MySlice []string
}
func TestSomething(t *testing.T) {
Whenever(fake.GetStuff(RequestThat(Should(MatchAllFields(
Fields{"MyString": ContainSubstring("abcd"), "MySlice": HaveLen(7)}))))).
ThenReturn("some stuff")
// ...
}
// It would be nice to not have to write one of these for each argument type
func RequestThat(matcher pegomock.Matcher) Request {
pegomock.RegisterMatcher(matcher)
return Request{}
} So my suggestion would be to generate the |
Hey @yhrn, sorry for the delay. Thanks a lot for the example for (2). Yes, that makes it a lot easier to understand, and yes, I think that's a good idea. I like it! So yes, let's go with your proposal to address 1&2, skip 3&4 for now, and move 5 into a separate issue. 👍 Thanks, |
Great, and no stress - it's not like these suggestions are critical. Just wanted to get rid of some more boilerplate. I'll try to get to this later this week. |
BTW, there is now already an issue for the variadic arguments here: #112 I believe this is the same as yours. So no need to open. A separate issue for 5. |
@petergtz would you consider releasing a new version now? At that point I think we could close this one. We can discuss the Gomega matcher integration separately but I have looked a bit more and I don't think it will work cleanly. Gomega matchers have no description outside of the context of an actual value, only failure messages that compare to an actual value. For pegomock matchers the Stringer description is the important thing, the failure message only seems to be used for invocation count matchers so I can't come up with a generic way of providing a good matcher description, each Gomega matcher type would have to be treated separately. |
Actually, thinking a bit more about custom matchers I feel that this could be simplified further so I created #114. Let me know what you think. |
We could, yes. It depends how urgently you need this to be on master. If it's not super urgent, I'd like your other PR to be merged as well, and then we can release it as one new version. Otherwise, let me know, and I'll make a new release. |
I agree, I'd rather wait for the other PR to be merged first. |
Just made a new release v2.9.0. |
I'm closing this old issue as I think everything has been addressed. If not, please open a new issue. A lot of things around matchers have changed with the latest version, now that Go has generics. |
Hi and thanks for a great mocking framework!
I just started using Pegomock and I found a few things related to the experience of using matchers that I would like to discuss. There are three main use cases that I found a bit cumbersome.
NotEq
matcher and if I write one of those I also need to write a matcher function for each type I want to match even if the matcher can handle any type.go fmt
to modify them (not a big deal but a bit annoying)I have some suggestions for how this could be addressed:
NotEqMatcher
and generate a matcher function for it as part of matcher generationXThatSatisfies(matcher pegomock.Matcher)
function as part of matcher generationWhat are your thoughts on this?
The text was updated successfully, but these errors were encountered: