any matcher and creating matchers for structures
godolatry opened this issue · 9 comments
I see that pegomock has specific matchers for strings and other basic objects, but I can't see an "any" matcher. Have I missed something?
Also, when I create my own structures, is it possible to use matchers for them?
Since Go does not have generics, it's not possible to write a generic Any
matcher. The matcher must return a proper type. It cannot just return interface{}
, because that wouldn't satisfy the mocks function signature.
You should be able to create your own matchers very easily though. Have a look at matcher_factories.go
. I think something like this should work:
func AnyMyType() MyType {
RegisterMatcher(&matcher.AnyMatcher{Type: reflect.Struct})
return MyType{}
}
I think at some point I will add the auto-generation of some default matchers based on the types used in the interface signatures for which a mock is generated. For the time being, they must be added manually though.
Hope this helps.
Or do you mean:
func AnyMyType() MyType {
RegisterMatcher(&matcher.AnyMatcher{Type: reflect.Struct})
return nil
}
which follows the style of the existing "Any..." matchers - they all
seem to return an appropriate zero value.
Question is, where do I put this function?
matcher is an internal package so I can't import it into my code. This
means that I can't add the method shown above to my test module.
As far as I can see, I would have to hack the pegomock code that I have
downloaded and add my matcher method there, which seems like a bad idea.
Am I missing something obvious?
On Sat, Sep 3, 2016 at 8:32 PM, Peter Götz notifications@github.com wrote:
Since Go does not have generics, it's not possible to write a generic Any
matcher. The matcher must return a proper type. It cannot just return
interface{}, because that wouldn't satisfy the mocks function signature.You should be able to create your own matchers very easily though. Have a
look at matcher_factories.go. I think something like this should work:func AnyMyType() MyType {
RegisterMatcher(&matcher.AnyMatcher{Type: reflect.Struct})
return MyType{}
}I think at some point I will add the auto-generation of some default
matchers based on the types used in the interface signatures for which a
mock is generated. For the time being, they must be added manually though.Hope this helps.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
#22 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AIfV71bGnFlKOP0BH4QZCGK0mPJZoCi_ks5qmcs9gaJpZM4Jzce3
.
The zero value for MyType
is MyType{}
. nil
can only be used for pointer types, i.e. *MyType
. So it depends on the method signature in your interface.
You're right that matcher
is not visible outside. That's a bug. I will try to fix it soon, but feel free to provide a pull request, if you need it now.
Thanks.
@godolatry Does this solve your issue?
I'm away at present. I will try this tomorrow (Friday)
Thanks and Regards
Simon
On Wednesday, September 7, 2016, Peter Götz notifications@github.com
wrote:
@godolatry https://github.com/godolatry Does this solve your issue?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#22 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AIfV76ljUyBB6YfrQwHSICazsANle7Spks5qnoINgaJpZM4Jzce3
.
That seems to work, but it only allows me to create a matcher for one of my own own structures. This is because of the "reflect.Struct" part:
func AnyMyType() MyType {
pegomock.RegisterMatcher(&matcher.AnyMatcher{Type: reflect.Struct})
return MyType{}
}
I also need to create a matcher for an interface type.
For example, assume I have defined interfaces A and B plus a structure C. I have objects of those types called a, b and c. Both a and b are mocks. My application makes this call:
a.fun(b, c)
If I need to write a WHEN that uses a matcher for c, then I must supply matchers for all of the parameters, so I need something like:
pegomock.When(a.fun(EqB(b), EqC(c)))
So I need to create a matcher for b, which is an interface with a mock behind it.
Is that possible?
Hi @goblimey,
Can you try with reflect.Interface
instead of reflect.Struct
when MyType
is an interface? Something like this:
func AnyMyType() MyType {
pegomock.RegisterMatcher(&matcher.AnyMatcher{Type: reflect.Interface})
return MyType{}
}
I will try this out myself as soon as possible, but maybe it already solves your problem.
@goblimey, @godolatry (you are both called Simon. Are you the same person actually?)
I've just pushed a change which will now properly support custom any-matchers based on interface types.
E.g. if you want to write a custom matcher for the error
interface, you would do it like this:
func AnyError() error {
RegisterMatcher(NewAnyMatcher(reflect.TypeOf((*error)(nil)).Elem()))
return nil
}
The TypeOf
construct looks a bit convoluted, but it's the recommended way.
Let me know if this solves your issue. Thanks.
@goblimey, @godolatry I'm closing this issue due to inactivity. Feel free to re-open, if you don't think the issue is solved.