Chained method calls for stubs in mockito?

4,504 views
Skip to first unread message

Jagger

unread,
Mar 21, 2008, 6:57:01 PM3/21/08
to mockito
Hello,

EasyMock has a very useful feature of chaining the mock methods
invocations,
here is an example from EasyMock 2.2 documentation.

Changing Behavior for the Same Method Call

It is also possible to specify a changing behavior for a method. The
methods times, andReturn, and andThrow may be chained. As an example,
we define voteForRemoval("Document") to

* return 42 for the first three calls,
* throw a RuntimeException for the next four calls,
* return -42 once.

expect(mock.voteForRemoval("Document"))
.andReturn((byte) 42).times(3)
.andThrow(new RuntimeException(), 4)
.andReturn((byte) -42);

Is it possible to make such a chain using a stub created with Mockito?

In the documentation of Mockito.stub method it is written:

" Once stubbed, mocked method will always return stubbed value
regardless of how many times it is called.
Last stubbing is more important - when you stubbed the same method
with the same arguments many times."

Am I missing something or such chaining is impossible with Mockito
stubs?

--
Best regards
Jagger

szczepiq

unread,
Mar 21, 2008, 8:11:20 PM3/21/08
to moc...@googlegroups.com
Hi,

> Am I missing something or such chaining is impossible with Mockito
> stubs?

You're right - chaining return values is impossible in Mockito.

We talked about this feature here:
http://groups.google.com/group/mockito/browse_thread/thread/e73e29d649a3b80a

Do you often use this feature? I never used it and I couldn't find a
good scenario to justify it. On the contrary: it doesn't promote
simple and focused test methods (look at the example from EasyMock -
it's a bit scary...). Do you want it in Mockito?

Cheers,
Szczepan Faber

Jagger

unread,
Mar 24, 2008, 2:51:14 PM3/24/08
to mockito
On 22 Mar, 01:11, szczepiq <szcze...@gmail.com> wrote:

> Do you often use this feature? I never used it and I couldn't find a
> good scenario to justify it.

Here is my scenario. It is taken from a real project
that I'm working on. There are some interfaces that
I wrote the implementation for.

public interface Meter {
void connect();

void close();

java.util.Map readValues();
}

public interface MeasurementListener {

void processEvent(MeasurementEvent measurementEvent);

void measurementStarted(MeasurementEvent measurementEvent);

void measurementStopped();
}

The above interfaces are the ones that I want to mock.

The class under testing is implementing the interface shown below.

public interface Measurement {

void addMeasurementListener(MeasurementListener measurementListener);

void removeMeasurementListener(MeasurementListener
measurementListener);

void start();

void interrupt();

boolean isStopped();
}

The start() method from the Measurement interface calls readValues()
from
Meter interface several times until the measurement is interrupted or
some
final value is reached. I want to stub readValues method so i returns
a 10 different
measurement point in a row. Then I simply want to check whether mocked
MeasurementListener was notified with appropriate events.
With EasyMock it is possible with chaining but it is
really annoying because I am forced to check whether connect() and
close() method
are also invoked (and I simply don't want to do that because of the
blown code).
As I wrote at the beginning this is taken from the real project and I
think such
functionality should be added to Mockito. Right know I have two
choices: switch
back to EasyMock or use both EasyMock and Mockito. Both choices are
bad :),
so please consider adding chaining to Mockito.

--
Best regards
Jagger

Jagger

unread,
Mar 24, 2008, 4:12:35 PM3/24/08
to mockito
I have read the previous discussion on the topic
and i begin to wonder whether "hand made" stub
is better in my case. It will certainly be "neater" than
a long chain of stub method invocations. It will also
for sure keep the test code simpler.

--
Best regards
Jagger

szczepiq

unread,
Mar 24, 2008, 4:18:20 PM3/24/08
to moc...@googlegroups.com
That's what I would suggest: hand written stub.

Anyway, I will look deeper at your example soon. Maybe stubs with
ability to 'stack' different answers is the way to go...

Thanks,
Szczepan Faber

Jagger

unread,
Mar 25, 2008, 11:52:44 AM3/25/08
to mockito


On 24 Mar, 21:18, szczepiq <szcze...@gmail.com> wrote:
> That's what I would suggest: hand written stub.
>
> Anyway, I will look deeper at your example soon. Maybe stubs with
> ability to 'stack' different answers is the way to go...

My final answer is: 'yes, I want it!'.
Today it turned out that there are too
so many scenarios that I want to test
that I would be forced to write a separate
stub for each of them or complicate logic
of the existing ones.

Looking forward to changes in Mockito. :)

--
Best regards
Jagger

szczepiq

unread,
Apr 16, 2008, 4:32:38 PM4/16/08
to moc...@googlegroups.com
I took me long time to get back to this thread/feature but I'm on it :D

>Today it turned out that there are too
>so many scenarios that I want to test
>that I would be forced to write a separate
>stub for each of them

'Forced' is such a bad word. I would say 'guided to do the right thing' :)

I can see that andReturn(1).andReturn(2).andReturn(null) can be useful
in cases where I deal with mocking *iterator-like objects*. But I
would argue that this happens very often and if it does then there are
better ways of testing it. The example you provided is indeed a case
of mocking an *iterator-like object* (Meter.readValues()).

However for other cases (e.g. non-iterators), I think that being
forced to write separate stub is a good thing. Can you show some code
that proves me wrong?

I looked again at your example with Meter.readValues() method:

>I want to stub readValues() method so it returns a 10 different

So your test ends up like that (I will use hypothetical syntax):

stub(meter.readValues())
.toReturn(mapOne)
.thenReturn(mapTwo)
.thenReturn(mapThree)
.thenReturn(mapFour)
.thenReturn(mapFive)
.thenReturn(mapSix)
.thenReturn(mapSeven)
.thenReturn(mapEight)
.thenReturn(mapNine)
.thenReturn(mapTen)
.thenReturn(emptyMap);

Isn't it a bit overkill to chain 10 return values on a mock to prove
correctness of some conditional logic (e.g. creation of events based
on values from meter)?

But ok, let's stick to your example with mocking 10-element iterator.

Mockito doesn't support mocking iterators. I'm forced to think more
about code under test...

Whoever uses Meter is probably doing something like that:

Map map = meter.readValues();

while (!map.isEmpty()) {

//***** all that conditional logic that require 10
different maps to assert that it works ****

map = meter.readValues();
}

What if Meter extended Iterable interface?

interface Meter extends Iterable<Map> {
void connect();
void close();
}

Then, whoever uses meter would do this:

foreach(Map values : meter) {

//***** all that conditional logic that require 10
different maps to assert that it works ****

}

Suddenly stubbing (even using Mockito!) becomes easy:

List maps = asList(mapOne, mapTwo, mapThree, mapFour, mapFive, mapSix,
mapSeven, mapEight, mapNine, mapTen, emptyMap);
stub(meter.iterator()).toReturn(maps.iterator());

What do you say - is it better now?


Finally, here is my dilemma: shall I implement
thenReturn().thenReturn() so that:

+ i can mock iterators
- there will be tests with 10X thenReturn() in my codebase, that can
be implemented better and tested nicer.

or not, and then:

+ i don't mock iterators: tests are simple and the code is forced to
be simple (hopefully)
- not having thenReturn() may be considered as a weakness so people
will still use current mocking libraries. There will be tests with 10X
andReturn() anyway because other mocking libraries can do that.

Or maybe I'm just still waiting for a good example... :D

Cheers,
Still-thinking-about-it Szczepan Faber

Jagger

unread,
Apr 17, 2008, 3:47:46 AM4/17/08
to mockito
It looks like a good idea. I will do some quick refactoring
and let you know how it affected my test classes and whether
I'm happy with it or not. :)

Thanks for the reply.

Best regards,
Jagger

Jagger

unread,
Apr 17, 2008, 4:09:41 AM4/17/08
to mockito
After some time of strong thinking...

What about throwing exceptions?
I not only want to test "normal situations".
Meter may got disconnected after five successful
measurement and then throw an exception.

There is also a scenario that meter "is allowed"
to throw three exceptions in a row (due to
some corrupted data) and then return to a normal state.

Iterator throwing an exception is not a good idea here
i guess. :) However all my exceptions are unchecked
so there should be no problem but I have doubts whether
it does not break iterator contract. :)

--
Best regards
Jagger

Jagger

unread,
Apr 17, 2008, 4:14:03 AM4/17/08
to mockito
> Iterator throwing an exception is not a good idea here
> i guess. :) However all my exceptions are unchecked
> so there should be no problem but I have doubts whether
> it does not break iterator contract. :)

Ok, I will answer myself. :)

List maps = asList(mapOne, mapTwo, mapThree, mapFour, mapFive, mapSix,
mapSeven, mapEight, mapNine, mapTen, emptyMap);
stub(meter.iterator()).toReturn(maps.iterator());

It is impossible to "put" an exception on the list. :)

szczepiq

unread,
Apr 17, 2008, 6:48:04 AM4/17/08
to moc...@googlegroups.com
> It is impossible to "put" an exception on the list. :)

That's a fair point :) Can you show us the code that uses Meter object?

Cheers,
Szczepan Faber

Jagger

unread,
Apr 17, 2008, 7:15:49 AM4/17/08
to mockito


On 17 Kwi, 12:48, szczepiq <szcze...@gmail.com> wrote:
> > It is impossible to "put" an exception on the list. :)
>
> That's a fair point :) Can you show us the code that uses Meter object?

No problemo (formatting will probably be lost). The instances of
classes
implementing Meter interface are firstMeter and secondMeter.

int ioExceptionsIgnored = 0;
while (!finishChecker.isFinished(firstValue) && !
interrupted) {
try {
Map<Magnitude, MeasurementValue> secondMetValues =
secondMeter
.readValues();
Map<Magnitude, MeasurementValue> firstMetValues =
firstMeter
.readValues();
ioExceptionsIgnored = 0;
postMeasurementEvent(firstMetValues,
secondMetValues);
firstValue =
firstMetValues.get(firstMagnitude).getValue();
} catch (MeterException e) {
if (++ioExceptionsIgnored >
MAX_IO_EXCEPTIONS_IGNORED) {
throw e;
}
logger
.log(
Level.WARNING,
"Cannot read values from one of
the meters. Retrying...",
e);
}
}

Mwanji Ezana

unread,
Apr 17, 2008, 8:16:14 AM4/17/08
to moc...@googlegroups.com
If what you really want to test is "what happens when too many exceptions are thrown?" why not lower the value of MAX_IO_EXCEPTIONS_IGNORED to 1 and have the two meter instances throw exceptions?

Mwanji

Jagger

unread,
Apr 17, 2008, 8:25:26 AM4/17/08
to mockito


On 17 Kwi, 14:16, "Mwanji Ezana" <mwa...@gmail.com> wrote:
> If what you really want to test is "what happens when too many exceptions
> are thrown?" why not lower the value of MAX_IO_EXCEPTIONS_IGNORED to 1 and
> have the two meter instances throw exceptions?
>

Simply, because I want to test such a scenario
- five value maps are returned in a row;
- then there are some communication problems or somebody
has disconnected the meter but connected it immediately back again
(for example it causes MeterException to be thrown twice);
- after quick recovery five values are returned again in a row.

Simply speaking I want some values returned in a row then
two exceptions and then some values again. Now I must
write a stub by myself to test such scenarios.

--
Best regards
Jagger

Steve Freeman

unread,
Apr 17, 2008, 8:59:07 AM4/17/08
to moc...@googlegroups.com
Or switch to jMock...

(sorry, Off-Topic. I couldn't help myself :)

S

On 17 Apr 2008, at 13:25, Jagger wrote:
> Simply speaking I want some values returned in a row then
> two exceptions and then some values again. Now I must
> write a stub by myself to test such scenarios.


Steve Freeman
http://www.mockobjects.com

Winner of the Agile Alliance Gordon Pask award 2006

Mwanji Ezana

unread,
Apr 17, 2008, 9:05:07 AM4/17/08
to moc...@googlegroups.com
On Thu, Apr 17, 2008 at 2:25 PM, Jagger <Pawel...@gmail.com> wrote:


Simply, because I want to test such a scenario
- five value maps are returned in a row;
- then there are some communication problems or somebody
has disconnected the meter but connected it immediately back again
(for example it causes MeterException to be thrown twice);
- after quick recovery five values are returned again in a row.

This sounds more like an integration test than a unit test, though, doesn't it?

Mwanji

Jagger

unread,
Apr 17, 2008, 9:12:42 AM4/17/08
to mockito
On 17 Kwi, 15:05, "Mwanji Ezana" <mwa...@gmail.com> wrote:

> This sounds more like an integration test than a unit test, though, doesn't
> it?
>
> Mwanji

Nope, I don't think so. :)

--
Best regards
Jagger

Jagger

unread,
Apr 17, 2008, 9:18:16 AM4/17/08
to mockito


On 17 Kwi, 14:59, Steve Freeman <smgfree...@gmail.com> wrote:
> Or switch to jMock...
>
> (sorry, Off-Topic. I couldn't help myself :)
>
> S

Maybe it is something that I'm going to do. :)
I remember that jMock 1 sucks because of
poor refactoring possibilities but I see that
there is version no. 2 available. Maybe I'm
gonna give it a try...

--
Best regards
Jagger

szczepiq

unread,
Apr 17, 2008, 5:30:21 PM4/17/08
to moc...@googlegroups.com
>Or switch to jMock...

No thanks, tried that. Didn't work, as I already told you :D

Let's get back to the Meter.

>- five value maps are returned in a row;
>- then there are some communication problems or somebody
>has disconnected the meter but connected it immediately back again
>(for example it causes MeterException to be thrown twice);
>- after quick recovery five values are returned again in a row.

As Mwanji says, it looks more like an integration test to me.

I wouldn't test the 'for' loop using 5 examples. The maximum should be
2. We all agree that the 'for' loop is pretty much stable feature of
java, right? :)

The problem at hand is the retry mechanism that makes the whole thing
difficult to test. How would I make it simpler? For example, I could
hide away the trickiness of try-ooups-retry in some kind of
RetryingMeter that decorates the Meter (or multiple meters). After
all, it's the contract of the Meter that says: "if I fail, try again
up to X number of times". Maybe it's nicer to keep that retry logic
away from clients of the Meter class.

The only problem now is how to test RetryingMeter (I don't have to
show the code here, do I? It's just a decorator that retries...). In
order to do that using the best mocking library is... roll your own
mock. It seems mockito needs this:

stub(meter.readValues())
.toReturn(foo)
.toThrow(new RuntimeException())
.toReturn(bar);

Me and Felix tried to investigate what's better in the case of retry
mechanism: rolling own mock or stretching the mock library. We will
document our findings soon. I'm getting convinced that this feature is
a cool thing. I'm just a bit scared how easily can it be abused to
write code that smells funny.

Cheers,
Szczepan Faber

PS.
Jagger, go try jmock and tell us what you think! Just be lenient for Steve...

Jagger

unread,
Apr 18, 2008, 4:14:47 AM4/18/08
to mockito
On 17 Kwi, 23:30, szczepiq <szcze...@gmail.com> wrote:

> The problem at hand is the retry mechanism that makes the whole thing
> difficult to test. How would I make it simpler? For example, I could
> hide away the trickiness of try-ooups-retry in some kind of
> RetryingMeter that decorates the Meter (or multiple meters). After
> all, it's the contract of the Meter that says: "if I fail, try again
> up to X number of times". Maybe it's nicer to keep that retry logic
> away from clients of the Meter class.

Well, at first sight it looks like a great idea. But what do I return
from
readValues() if an "acceptable" exception occurs? The decorated method
would look something like that:

public Map<Magnitude, MeasurementValue> readValues() {
try {
Map<Magnitude, MeasurementValue> result =
meter.readValues();
retryCount = 0;
return result;
} catch (MeterException e) {
if (++retryCount > maximumNumberOfRetries) {
throw e;
}
return null; //???
}
}

The only solution is to return null which in this case is overloaded
and means an exceptional situation occured. If so then I am forced
to check in measurement method whether a map returned from
readValues()
is not null. It complicates logic and null meaning is overloaded.
If so, why not resign from this method throwing an exception at all?

Then it will be possible to test it like:

List maps = asList(mapOne, mapTwo, mapThree, null, null, null,
mapSeven, mapEight, mapNine, mapTen);

Or maybe return an empty map instead of null...

Nevertheless all these look smelly to me. :)

--
Best regards
Jagger

Jagger

unread,
Apr 18, 2008, 5:05:22 AM4/18/08
to mockito
Ok, certainly I am not in a good shape these days. :)
It is sufficient to move while loop into RetryingMeter
and it looks a great idea also at second sight. :)

--
Best regards
Jagger

Steve Freeman

unread,
Apr 20, 2008, 8:12:14 AM4/20/08
to moc...@googlegroups.com
You might want to start by distinguishing between an empty collection
(no values) and null (something wrong). The convention I use for
returning collections is always to return one, it makes the client
code much simpler.

Another option to consider is wrapping the Map in a more meaningful
object which you would be able to query about its situation. I'm
developing an increasing aversion to unwrapped collections.

S.

Steve Freeman

szczepiq

unread,
Apr 26, 2008, 2:42:01 PM4/26/08
to mockito
Felix blogged about this feature of here: http://wuetender-junger-mann.de/wordpress/?p=568

I started implementing it.

Cheers,
Szczepan Faber
> Winnerof the Agile Alliance Gordon Pask award 2006

Marc-Andre Houle

unread,
Jun 17, 2008, 9:05:23 AM6/17/08
to mockito
Is the implementation going well? Will it be included in the next
release?

Iterator, resultset and statefull object are corner test for mocking
libraries, but I think Mockito could gain visibility out of this. I
am running a pilot project to include Mockito in our environment. When
I asked a dude to tell me an object he would want me to mock in a
presentation, is first thought was about ResultSet or an Iterator of
ResultSet because they are "difficult to test". Right away, I could
not answer his question.

This is something that would not be used too often, but it would be
used in the checked list of a programmer to know if it is worth
listening. I would really appreciate Mockito to have this
functionality....

Thanks in advance.

Marc-Andre

szczepiq

unread,
Jun 17, 2008, 9:20:41 AM6/17/08
to moc...@googlegroups.com
Hi,

It is already in trunk. Snapshot builds can be downloaded here:
http://hudson.ramfelt.se/job/Mockito

I'm hoping to release 1.4 pretty soon.

My advice about mocking ResultSet: don't :). Few days ago my friend
showed me a really nice implementation of hand made stub for
ResultSet. It was based of 'fluent builder' pattern and it really
looked very nice in test methods.

Cheers,
Szczepan Faber

On Tue, Jun 17, 2008 at 3:05 PM, Marc-Andre Houle <mho...@gmail.com> wrote:
>
> Is the implementation going well? Will it be included in the next
> release?
>
> Iterator, resultset and statefull object are corner test for mocking
> libraries, but I think Mockito could gain visibility out of this. I
> am running a pilot project to include Mockito in our environment. When
> I asked a dude to tell me an object he would want me to mock in a
> presentation, is first thought was about ResultSet or an Iterator o

Steve Freeman

unread,
Jun 18, 2008, 9:29:12 AM6/18/08
to moc...@googlegroups.com
I cannot second this strongly enough. Especially at the beginning, try
to avoid mocking third-party types. Write your own domain-specific
code that describes the problem, then have a thin veneer that maps
that to underlying implementations like ResultSet. Write a little
integration test around that veneer to make sure it works like it's
supposed to.

No, really, don't start there.

S.

On 17 Jun 2008, at 14:20, szczepiq wrote:
> My advice about mocking ResultSet: don't :). Few days ago my friend
> showed me a really nice implementation of hand made stub for
> ResultSet. It was based of 'fluent builder' pattern and it really
> looked very nice in test methods.

Steve Freeman
http://www.mockobjects.com

Winner of the Agile Alliance Gordon Pask award 2006

Reply all
Reply to author
Forward
0 new messages