Currently I work on exposing the default return values. It's gonna be
fully configurable via ReturnValuesProvider interface so that
developers can build any default behaviours for stubs.
I'll update this thread soon and describe the API.
Cheers,
Szczepan Faber
ArgumentMatcher has a generic parameter T (the type of object I want to
match). And it has the "matches" func (by some mysterious internal
reasons the argument doesn't have the type T:
public abstract boolean matches(Object argument)
So, in the matches func I have to check if the argument really of the
type I want. For example, if I write a matcher:
public class SomeMatcher extends ArgumentMatcher<MyType> {
public boolean matches(Object argument) {
// !!!
if ( argument instanceof MyType ) {
... blah-blah
}
else
return false;
}
}
the argument I got in the "matches" func isn't necessarily of the type
"MyType" so I have to check it using instanceof. It's not convenient
and, as a Mockito user, I don't understand why generics are used at all
- they are useless for me here. Can Mockito check the argument type
itself before passing it to the custom matcher?
Vitaly Berov
matches() method doesn't take T because (quoting javadoc from hamcrest Matcher):
This method matches against Object, instead of the generic type T. This is
because the caller of the Matcher does not know at runtime what the type is
(because of type erasure with Java generics). It is down to the
implementations
to check the correct type.
Although I find it annoying as well, I cannot change it in order to
keep argument matchers compatible with hamcrest (e.g: keep the
compiler happy...).
> the argument I got in the "matches" func isn't necessarily of the type
> "MyType" so I have to check it using instanceof.
For my own matchers, I never use instanceof. ClassCastException is
more useful to me because it tells me that I'm using the matcher
wrongly.
> and, as a Mockito user, I don't understand why generics are used at all
There is one little thing that makes them useful (apart from being
compatible with hamcrest): You can avoid one additional explicit
casting. Example:
//without generics:
verify(mock).foo((String) argThat(new IsStringContainingBar()));
//with generics:
verify(mock).foo(argThat(new IsStringContainingBar()));
Have a look at signature of argThat() method.
Cheers,
Szczepan Faber
Thanks for the detailed answer.
In my situation, I have a mocked obj with func which takes an interface
as a parameter, and I want to check that it was called with a specific
class instance.
Can you tell more a little bit how you use ClassCastException?
> For my own matchers, I never use instanceof. ClassCastException is
> more useful to me because it tells me that I'm using the matcher
> wrongly.
Vitaly
Oups, I wasn't clear enough. Here is what I usually do in my matchers:
matches(Object o) {
// I don't do any instanceof checks because I want
ClassCastException to be thrown
// ClassCastException does better job in communicating that I'm
using the matcher with wrong object.
SomeObject s = (SomeObject) o;
}
Cheers,
Szczepan Faber
If you look at trunk, following tests show how to configure default
return values:
http://code.google.com/p/mockito/source/browse/trunk/test/org/mockitousage/examples/configure/ConfiguringDefaultReturnValuesTest.java
http://code.google.com/p/mockito/source/browse/trunk/test/org/mockitousage/examples/configure/ConfiguringDefaultReturnValuesForSelectedMocksTest.java
Basically, default return values for stubs are no longer 'sealed'. You
can configure them (see examples). The Mockito API still stays slim -
it's up to the team if they want to build their own ReturnValues
implementation, depending on what kind of code they work on (e.g: more
intelligent stubs may be helpful for legacy code).
Let me know if this is anything useful.
Cheers,
Szczepan Faber
Thanks
Szczepan Faber
S.
Steve Freeman
http://www.mockobjects.com
Winner of the Agile Alliance Gordon Pask award 2006
Agreed.
On the other hand, changing the default return value from plain null
to a proper mock is the matter of configuration to me. It can be
'turned on' in the case of working with legacy code, etc to achieve
slightly different 'style' of mocking. That's why I'm working on
exposing this configuration so that the team can decide how they want
to 'mock'.
As Kris wrote initially, they rolled their own build with custom
interceptor to return mocks instead of nulls. Custom build is a bit of
pain. Letting the library to expose some configuration can be a
remedy. However, I'm not very keen on adding static methods to the API
like: autoFakeReturnValues(mock), autoReturnTrue(mockOne, mockTwo),
autoReturnStrings(mock, "foo"), etc.
Have a look at draft examples below (it's best to see them in IDE, though).
http://code.google.com/p/mockito/source/browse/trunk/test/org/mockitousage/examples/configure/withstaticutility/ConfiguringSelectedMocksToReturnFakesTest.java
http://code.google.com/p/mockito/source/browse/trunk/test/org/mockitousage/examples/configure/withbaseclass/ConfiguringDefaultReturnValuesUsingBaseClassTest.java
http://code.google.com/p/mockito/source/browse/trunk/test/org/mockitousage/examples/configure/withrunner/ConfiguringDefaultReturnValuesUsingRunnerTest.java
Mwanji writes that there is too much boilerplate code but I think that
it depends on the client implementation. The entry point to configure
default values is simply:
MockitoConfiguration.instance().setReturnValues(customReturnValues);
and
public interface ReturnValues {
Object valueFor(InvocationOnMock invocation);
}
In the examples I tried to use different ways of implementing shared
code, e.g. base class, junit runner, static utility.
Cheers,
Szczepan Faber
PS.
Mwanji,
>Mockito.mock(MyClass.class).autoFakeReturnValues()
This is impossible because mock() method returns an object of a specific type :(