How to stub a method with a parameter that has specifics properties ?
For example :
doReturn(true).when(object).method(
// an object that has a property prop1 equals to "myprop1"
// and prop2 equals to "myprop2"
)
How to stub a method with a parameter that has specifics properties ?
For example :
doReturn(true).when(object).method(
// an object that has a property prop1 equals to "myprop1"
// and prop2 equals to "myprop2"
)
You're going to need either a custom Mockito matcher or a Hamcrest matcher for this problem, or a hybrid of the two. The two work a little differently, but you can use them together with adapters.
You'll need to use Matchers.argThat
(Mockito 1.x) or MockitoHamcrest.argThat
(Mockito 2.x) to adapt the Hamcrest hasProperty
matcher and combine it.
doReturn(true).when(object).method(
argThat(allOf(hasProperty("prop1", eq("myProp1")),
hasProperty("prop2", eq("myProp2"))))
)
Here, argThat
adapts a Hamcrest matcher to work in Mockito, allOf
ensures you're only matching objects that satisfy both conditions, hasProperty
inspects the object, and eq
(notably Hamcrest's eq
, not Mockito's eq
) compares string equality.
Mockito no longer depends directly on Hamcrest as of Mockito v2.0 (in beta now), so you may want to do the same logic with Mockito's ArgumentMatcher class in a similar style.
doReturn(true).when(object).method(
argThat(new ArgumentMatcher<YourObject>() {
@Override public boolean matches(Object argument) {
if (!(argument instanceof YourObject)) {
return false;
}
YourObject yourObject = (YourObject) argument;
return "myProp1".equals(yourObject.getProp1())
&& "myProp2".equals(yourObject.getProp2());
}
})
)
Naturally, this same custom matcher class technique works with Hamcrest too, but you might prefer the hasProperty
technique above if you're sure you're working with Hamcrest.
One word of caution: Though you are welcome to save Matcher objects however you'd like (returned in a static helper method or saved in a field), the call to argThat
has side effects, so the call must be made during the call to method
. In other words, save and reuse your Matcher
or ArgumentMatcher
instances if you want, but don't refactor out the call to argThat
unless you do so into a static method so argThat
still gets called at the right time.
// GOOD with Hamcrest's Matcher:
Matcher<YourObject> hasTwoProperties = (...)
doReturn(true).when(object).method(argThat(hasTwoProperties));
// GOOD with Mockito's ArgumentMatcher:
ArgumentMatcher<YourObject> hasTwoProperties = (...)
doReturn(true).when(object).method(argThat(hasTwoProperties));
// BAD because argThat is called early:
YourObject expectedObject = argThat(...);
doReturn(true).when(object).method(expectedObject);
// GOOD because argThat is called correctly within the method call:
static YourObject expectedObject() { return argThat(...); }
doReturn(true).when(object).method(expectedObject());