Default Return Values

5,451 views
Skip to first unread message

Kris

unread,
Mar 6, 2008, 7:50:27 AM3/6/08
to mockito
Hi all,

I'm working on a fearly large project (around 30 developers) using
mainly EasyMock for automated testing. The Expect-replay step in
testing often turned out the be quite a hassle. Today someone
introduced me to mockito and it openened my eyes, finally seeing we
were mixing stubbing behaviour with expectations...

So I dived into the mockito docs and code.
One part we found annoying in EasyMock (as well as other mocking
frameworks) is the lack to configure the default return values. I've
got some questions regarding this topic:

1) The default return values for Mockito are 0 (zero) for int, null
for Integer, false for boolean, null for Boolean, ... Why did you
choose for this approach? Why returning null for Integer, because this
can typically lead to NullPointerExceptions due to autoboxing an
Integer from a mock to an int.

2) I traced the location of the default return values in the Mockito
source code to the class 'EmptyReturnValues'. I was surprised not to
find 'int' and 'boolean' in this list. So I started debugging to find
out how this was implemented, but I cannot find it. If you call a
method returning an int or boolean on a mock that has no stubbing
behaviour configured, the "intercept" method on
"MethodInterceptorFilter" is called. This method returns null, even
when the return type of the method is 'int'. How come this doesn't
result in a NullPointerException due to autoboxing? Is it Objenesis
that does this transformation behind the scene? (converting null to 0
for return type int and converting null to false for return type
boolean)

3) Why didn't you make these default return types configurable?
Currently they are listed in a static method. Hence, the only way to
create a different behaviour is to adapt that file and create a custom
build.

4) Lastly, why did you choose null as the default fallback return
type? In our project we created a custom interceptor returning a mock
as default fallback return type instead of null. This results in less
stubbing-setup for your test and less NullPointerExceptions. Quite
Handy ...

Thanks for the information,
Nice job creating Mockito,

Kris

szczepiq

unread,
Mar 6, 2008, 9:14:36 AM3/6/08
to moc...@googlegroups.com
Hi Kris,

Short answers for now because I don't have a lot of time:


>1) The default return values for Mockito are 0 (zero) for int, null
>for Integer, false for boolean, null for Boolean

Also empty collections for collection-returning methods. About Boolean, Integer to return null. I didn't think about methods that return Boolean, Integer. I think it's a good idea to return Boolean.FALSE, Integer.valueOf(0) in that cases. I would be more consistent. What do other people think?

>2)  Is it Objenesis that does this transformation behind the scene?

It's probably cglib. I don't remember now :)


>3) Why didn't you make these default return types configurable?

For simplicity: the less powerful mocking library -> simpler test code -> simpler app code (if is test-driven :).

How would you want to have it configurable? Can you suggest an API for that? Is it mostly for legacy code or do you see a case for new code as well (e.g: show us *real* example).


>4) Lastly, why did you choose null as the default fallback return
>type?

Again, to promote simple code and explicit test methods. If an object (e.g. return value I ask for) is essential for the processing - then I think it should be described in the test method - by stubbing the mock that returns this object. I may be wrong, though :) Can you show us a *real* example where you find returning mock instead of null useful? And again: is it for dealing with legacy code or for new stuff?

>Nice job creating Mockito,

Thanks!

Szczepan Faber

Kris

unread,
Mar 6, 2008, 9:39:49 AM3/6/08
to mockito
Hi

Thanks for the quick response.

> >3) Why didn't you make these default return types configurable?
> >4) Lastly, why did you choose null as the default fallback return
> >type?
>
> For simplicity: the less powerful mocking library -> simpler test code ->
> simpler app code (if is test-driven :).
>
> How would you want to have it configurable? Can you suggest an API for that?
> Is it mostly for legacy code or do you see a case for new code as well (e.g:
> show us *real* example).

You are probably right.
For developing new code a 'simpler' mocking library will make you
think harder about the design of your application code, resulting in
better code.

In our project me mostly need it for legacy code, like you guessed.
This project started almost 3 years ago. Many developers, with varying
background, have worked on the code. During the years we have adjusted
our test vision. E.g. we started with JMock and our now mostly using
EasyMock. We encourage the developers to write the code test-first,
but it is far from trivial for all developers to effectively do this.
The result? A tangled domain model that evolved gradually (agile)
during those years. Writing new tests for the existing domain is quite
hard and in such cases mocks returning mocks can come in handy. Most
of the times when you would need such a feature, this indicates the
code smell 'Message Chains' :(

Kris

Mwanji Ezana

unread,
Mar 23, 2008, 12:38:43 AM3/23/08
to mockito
Hi,

I've started replacing EasyMock with Mockito and I've found it a big
step forward. However, like Kris, I've been bothered by the null
return values for objects. If you're returning empty collections (good
idea!), why not return a mock of custom objects? These objects would
be like auto-generated Fakes, and I don't want to have to set
expectations for them, precisely because they're not important for the
test.

You asked for a real example, so here's one:

We have a DaoFacade that groups all of our DAOs. If I'm testing a
method that calls two DAOs, I'll generally test each call separately -
you know, One Assertion Per Test. But since the method under test
does:

daoFacade.getFirstDao().getSomeStuff();
// ...
daoFacade.getSecondDao().getSomeOtherStuff();

then I need to mock the second DAO to avoid getting a NullPointer.
This just clutters my test, as I don't care about what happens with
the second DAO when I'm testing interaction with the first DAO, and
vice-versa.

I haven't really thought about an API for such a configuration option,
but I do think it could be helpful.

Mwanji

szczepiq

unread,
Mar 23, 2008, 12:45:20 PM3/23/08
to moc...@googlegroups.com
Hi,

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

Mwanji Ezana

unread,
Mar 23, 2008, 1:21:08 PM3/23/08
to moc...@googlegroups.com
That sounds great, I look forward to seeing it. Incidentally, I just finished writing a little solution to my problem using reflection on setters that I thought of after writing the mail, but it'll be nice to have a more generic solution.

Mwanji

Vitaly Berov

unread,
Mar 24, 2008, 1:04:01 PM3/24/08
to moc...@googlegroups.com
Hi,

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

szczepiq

unread,
Mar 24, 2008, 2:46:14 PM3/24/08
to moc...@googlegroups.com
Hi,

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

Vitaly Berov

unread,
Mar 25, 2008, 4:01:14 AM3/25/08
to moc...@googlegroups.com
Hi,

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


szczepiq

unread,
Mar 25, 2008, 7:53:51 AM3/25/08
to moc...@googlegroups.com
> Can you tell more a little bit how you use ClassCastException?

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

szczepiq

unread,
Mar 25, 2008, 2:12:39 PM3/25/08
to moc...@googlegroups.com
Hi,

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

Mwanji Ezana

unread,
Mar 26, 2008, 4:44:26 AM3/26/08
to moc...@googlegroups.com
Hi,

I've taken a look, and it seems to generate a lot of boiler-plate code (and forces me to remember to call the configuration methods on the static configuration object). I understand that you don't necessarily want to make this operation too easy, but I was kind of hoping to just be able to inject a return value handler into a specific mock instance. So all I'd be coding is the really relevant stuff:

            if (returnType == String.class) {
                return "";
            } else if (returnType == Boolean.TYPE) {
                return true;
            } else {
                return mock(returnType);
            }

Would that be possible? In my case, I think I could come up with a way to set custom return values for my project's domain objects, but I think having this feature in a really concise way in the framework out of the box would help write more focused and clearer tests.

Thanks for all your work on Mockito, it's much appreciated!

Mwanji

szczepiq

unread,
Mar 26, 2008, 2:30:30 PM3/26/08
to moc...@googlegroups.com
Let me think about it a little bit. I will update this thread soon.

Thanks
Szczepan Faber

Mwanji Ezana

unread,
Mar 26, 2008, 7:10:49 PM3/26/08
to moc...@googlegroups.com
Thinking about it a little more, maybe a good compromise could be something like:

Mockito.mock(MyClass.class).autoFakeReturnValues()

That, way, you don't have as much customisation power as in your code example, but you do have a possibly handy feature.

Mwanji

Steve Freeman

unread,
Mar 30, 2008, 2:55:40 PM3/30/08
to moc...@googlegroups.com
I would argue that if you need to chain mocks then it there should be
some "grit" in the process to make you look again at the code. Two
levels of mock should be occasional, three should be scary.

S.

Steve Freeman
http://www.mockobjects.com

Winner of the Agile Alliance Gordon Pask award 2006

szczepiq

unread,
Apr 3, 2008, 8:51:14 AM4/3/08
to moc...@googlegroups.com
>Two levels of mock should be occasional, three should be scary

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 :(

Reply all
Reply to author
Forward
0 new messages