Question about iterators and such

343 views
Skip to first unread message

yrebb

unread,
Feb 22, 2008, 9:50:16 AM2/22/08
to mockito
Hello,

I've been looking at Mockito vs. EasyMock 2.x as an upgrade from
EasyMock 1.x (my organization is finally moving to Java 5). I too
have been frustrated by having to set up expectations that I don't
care about (and put them before the actual testing) in EasyMock, so
the approach that Mockito takes really appeals.

There's one thing that I haven't been able to see how to handle in
Mockito, though, and I'm hoping that someone can enlighten me. There
are cases where a single method under test might call a mocked method
repeatedly with the same arguments and expect different results, i.e:
1) Using an iterator (repeated calls to hasNext()/next() returning
different results as you proceed through the collection)
2) Pulling messages from a JMS Queue (repeated calls to
MessageConsumer.receive())

In EasyMock you can handle this situation like this:
expect(mock.receive())
.andReturn(message1)
.andReturn(message1)

.andThrow(new RuntimeException(), 4)
.andReturn((byte) -42);

As I understand it, if I stub a method multiple times:
stub(mock.voteForRemoval("Document").toReturn(10).toReturn(;

yrebb

unread,
Feb 22, 2008, 9:53:27 AM2/22/08
to mockito
Sorry, got posted prematurely.
Let me try again:
In EasyMock you can handle this situation like this:
expect(mock.receive())
.andReturn(message1)
.andReturn(message2)
.andReturn(message3);

As I understand it, if I stub a method multiple times in Mockito:
stub(mock.receive()).toReturn(message1);
stub(mock.receive()).toReturn(message2);
stub(mock.receive()).toReturn(message3);

The method under test will only see message 3 no matter how many times
it calls receive().

So what's the right way to handle this in Mockito!



Igor Czechowski

unread,
Feb 22, 2008, 10:29:45 AM2/22/08
to moc...@googlegroups.com
Hi yrebb,

Thanks for taking a look at Mockito.

Correct, the current behavior is it will return the last stubbed
value, but I wonder do you relay need it ?

With Mockito you don't have to stub as many times as the method will
be invoked later, so
stub(mock.receive()).toReturn(message);

will satisfy any number of mock.receive() invocations and those
invocations won't be verified, you have to explicitly state how many
times you expect receive invocation to happen.

stub(mock, times(3)).receive(); //exactly 3 times

or maybe a little bit loosen constraint

stub(mock, atLeastOnce()).receive(); // any number but no less then 1

If you have any further question, don't hesitate to ask.

Cheers,
Igor

yrebb

unread,
Feb 22, 2008, 12:58:33 PM2/22/08
to mockito
Thanks for the quick response Igor!

I wasn't thinking of stubbing multiple times in order to verify the
number of calls, but rather to drive different behavior in the code
under test.

For example, if the sequence were:
message1=<process started>
message2=<process paused>
message3=<process resumed>

The code might respond to that sequence of messages in a different way
than it would to, say:
message1=<process started>
message2=<process started>
message3=<process started>

Of consider the case where someone would create a mock for a JDBC
result set object. The code under test might scroll through multiple
rows of the result set and build up some data structures. If all of
the rows pulled from the result set were identical, one might not be
able to exercise all paths of the code. In fact, it's unclear to me
how you would get the scrolling loop to read more than 0 rows and
still terminate, given that ResultSet.next() would always have to
return the same value for the duration of the method being tested.

Hope this helps to clarify what I am asking about.

Thanks,
yrebb

Igor Czechowski

unread,
Feb 22, 2008, 1:27:37 PM2/22/08
to moc...@googlegroups.com
Hi,

I thought you may need this functionality to test various conditional
login in the code, but for me these should be separate test cases. One
for each type of message. Unfortunately, when dealing with mocks each
test forces you to repeat the verification steps. More you can find
here http://www.martinfowler.com/articles/mocksArentStubs.html

However, when you don't use in order verification, I wouldn't afraid
to extract common verification steps to separate method with an
appropriate name and just add the parts of interactions, that differs
for various types of messages, afterwards

Nevertheless, we put this functionality on our TODO list and when more
requests come it will probably find it's place within Mockito.

If you can past some code here, we can work it out together to come
up with solution.

Cheers,
Igor

yrebb

unread,
Feb 22, 2008, 3:44:57 PM2/22/08
to mockito
Igor,
Thanks (and special thanks for the article link - I hadn't seen
that one yet and always enjoy Martin Fowler's articles.) I was
thinking of cases where sequencing of messages, results, etc. was part
of what was driving the logic, and specifically that a single method
would be reading all of the data (if a different invocation of the
method under test read each message, resultset row, etc. I think
that .)
The big picture of what I am doing is that I'm looking at mock
object frameworks not just for my own use, but to recommend to the
rest of the development teams in my company. I've worked with
EasyMock 1.x enough that I believe that I understand its strengths and
limitations, and EasyMock 2.x strikes me as the same basic approach
with some significant usability improvements. So what I'm trying to
do is not only find Mockito's strengths and advantages, but also kick
the tires and find ways in which the difference in approach that
Mockito takes might cause us problems or make things harder on us than
they would be with EasyMock.
This particular limitation doesn't concern me too much at the
moment - in looking through our existing tests, there are not too many
cases where this type of scenario comes up. I think that when we do
encounter cases like these we can use EasyMock or a hand-written stub
if need be. If Mockito eliminates as much code as I'm hoping that it
will, we'll still come out far ahead. :)
So for now I will just continue on, and I'll let you know if I
have any further questions or comments. Thanks again for your help!


szczepiq

unread,
Feb 22, 2008, 6:56:29 PM2/22/08
to moc...@googlegroups.com
>I think that when we do
>encounter cases like these we can use EasyMock or a hand-written stub
>if need be.

Exactly!

I designed Mockito interface with a crazy hope to improve not only test code quality but also app code quality.
I wanted the API to push back when test is getting to fancy: If I cannot tdd the code using mockito I design my code differently - to make it easier to test.
I've seen to many tests hacked badly thanks to over powerful features of test tools/mock libraries.

Stubbing is simplified on purpose (e.g: things like stub(times(3)) are not possible) to promote simple test methods. As you mentioned before, I can always craft a stub by hand for some edge cases. Regardless of any mock library - there is always a place for some hand written stubs.

I'm not saying NO to new features like powerful stubbing - time will show what's important for Mockito users and we will certainly react :)

Thanks for giving Mockito a try!
Szczepan Faber



  and if I ever want to stub such thing like iterator I'd probably craft a stub by hand.

Bartosz Bankowski

unread,
Feb 29, 2008, 2:13:52 PM2/29/08
to mockito
Just a trivial example to show why I think that multiple return values
are important:

private Iterator iterator;

public List myMethod() {
List list = new LinkedList();
while (iterator.hasNext()) {
Object object = iterator.next();
list.add(object);
}
return list;
}

I would like to have a test case that goes like this:
- prepare three objects
- stub iterator, which will return those three objects in a given
order
- invoke myMethod()
- verify the order of the list

It would be nice to upgrade toReturn method (sorry if it is not
possible to code with the approach you have, I am not very fluent in
Mockito, I've just started playing with it):

stub(myMock.myMethod()).toReturn(object1, object2, object3);

Regards,
Bartosz Bankowski

szczepiq

unread,
Mar 1, 2008, 5:10:19 AM3/1/08
to moc...@googlegroups.com
Hi Bartosz, I'm glad to have you here.

Does your example come from production code where you actually injected & mocked an iterator?

I justified features by analysing really large codebase. I've never seen chaining return values used even once. How often is it used in your codebase?

Simplified stubbing promotes smaller test methods, where you stub per single scenario. At least I hope so :)

Cheers,
Szczepan Faber

Bartosz Bańkowski

unread,
Mar 1, 2008, 6:30:10 AM3/1/08
to moc...@googlegroups.com
> I justified features by analysing really large codebase. I've never seen
> chaining return values used even once. How often is it used in your
> codebase?

It was based on a production code where plain JDBC is used and
ResultSet is my "iterator". I will try to find a part which I can send
here later on.

> Simplified stubbing promotes smaller test methods, where you stub per single
> scenario. At least I hope so :)

I gave you a single scenario which requires more advanced stubbing.

On the other hand I completely agree that stubs should be as simple as
possible. The same is true for test methods. One scenario for one test
method is what I always follow.

Regards,
Bartosz

szczepiq

unread,
Mar 1, 2008, 9:49:56 AM3/1/08
to moc...@googlegroups.com
>It was based on a production code where plain JDBC is used and
>ResultSet is my "iterator". I will try to find a part which I can send
>here later on.

Ok, so I assume you injected & mocked this iterator. Maybe I did not make myself clear: I've never seen chaining return values **on mocks** used even once in our massive codebase.


>I gave you a single scenario which requires more advanced stubbing.

   private Iterator iterator;

   public List myMethod() {
       List list = new LinkedList();
       while (iterator.hasNext()) {
           Object object = iterator.next();
           list.add(object);
       }
       return list;
   }

Well, in your scenario I just would not mock an iterator. Everything interesting in an iterator is the state: the elements. Why not just build a three-element list and inject list.interator(). Mocking always introduces more complexity, not to mention coupling with implementation details.

But I'd be interested in the case where multiple return values are really useful. Warm up your eclipse and start browsing... :)

Cheers,
Szczepan Faber

Bartosz Bankowski

unread,
Mar 3, 2008, 7:54:00 AM3/3/08
to mockito
> Well, in your scenario I just would not mock an iterator. Everything
> interesting in an iterator is the state: the elements. Why not just build a
> three-element list and inject list.interator(). Mocking always introduces
> more complexity, not to mention coupling with implementation details.

Sure, I would probably do something like you advised, but try to get
an iterator out of ResultSet :)

public ValueObject getValueObjectFromResultSet(ResultSet rs)
throws SQLException {
MyValueObject vo = null;
if (rs.next()) {
vo = new MyValueObject();
vo.setFieldOne(rs.getString(1));
vo.setSomethingElse(rs.getString(2));
}
return vo;
}

Not only next() is needed, but also getString(arg) can be called more
than once with the same argument.

Regards,
Bartosz

On Mar 1, 3:49 pm, szczepiq <szcze...@gmail.com> wrote:
> >It was based on a production code where plain JDBC is used and
> >ResultSet is my "iterator". I will try to find a part which I can send
> >here later on.
>
> Ok, so I assume you injected & mocked this iterator. Maybe I did not make
> myself clear: I've never seen chaining return values **on mocks** used even
> once in our massive codebase.
>
> >I gave you a single scenario which requires more advanced stubbing.
>
> private Iterator iterator;
>
> public List myMethod() {
> List list = new LinkedList();
> while (iterator.hasNext()) {
> Object object = iterator.next();
> list.add(object);
> }
> return list;
> }
>
> Well, in your scenario I just would not mock an iterator. Everything
> interesting in an iterator is the state: the elements. Why not just build a
> three-element list and inject list.interator(). Mocking always introduces
> more complexity, not to mention coupling with implementation details.
>
> But I'd be interested in the case where multiple return values are really
> useful. Warm up your eclipse and start browsing... :)
>
> Cheers,
> Szczepan Faber
>
> On Sat, Mar 1, 2008 at 11:30 AM, Bartosz Bańkowski <bbankow...@gmail.com>
> wrote:
>
>
>
> > > I justified features by analysing really large codebase. I've never seen
> > > chaining return values used even once. How often is it used in your
> > > codebase?
>
> > It was based on a production code where plain JDBC is used and
> > ResultSet is my "iterator". I will try to find a part which I can send
> > here later on.
>
> > > Simplified stubbing promotes smaller test methods, where you stub per
> > single
> > > scenario. At least I hope so :)
>
> > I gave you a single scenario which requires more advanced stubbing.
>
> > On the other hand I completely agree that stubs should be as simple as
> > possible. The same is true for test methods. One scenario for one test
> > method is what I always follow.
>
> > Regards,
> > Bartosz
>
> > > On Fri, Feb 29, 2008 at 7:13 PM, Bartosz Bankowski <bbankow...@gmail.com

szczepiq

unread,
Mar 3, 2008, 9:10:02 AM3/3/08
to moc...@googlegroups.com
I assume you want to do  while(rs.next())

This is how it could  look like if  I wanted to use mocks (and hypothetical new feature of Mockito :):
     
        ResultSet resultSet = mock(ResultSet.class);
       
        stub(resultSet.next()).toReturn(true, true);
        stub(resultSet.getString(1)).toReturn("fooOne", "barOne");
        stub(resultSet.getString(2)).toReturn("fooTwo", "barTwo");
        stub(resultSet.getDate(3)).toReturn(Date.now(), Date.now());
       
        ValueObject v = mapper.getValueObjectFromResultSet(resultSet);
       
        assertEquals...
       
And this what I would really do:
      
        ResultSet resultSet = new ResultSetBuilder()
            .row("fooOne", "fooTwo", Date.now())
            .row("barOne", "barTwo", Date.now())
            .toResultSet();
       
        ValueObject v = mapper.getValueObjectFromResultSet(resultSet);
       
        assertEquals...


The second snippet obviously requires to create stubs, builder, etc. But it's worth it: the test is not only more readable but is also more maintainable (and it's so easy to write another such test - I assume you have many resultSet->VO transformers).

In a case you have many RS->VO transformers I'd go for more generic solution...

Mockito pushes back and forces me to think about the code. I'd rather not mock things like ResultSet - it's just a collection of values. Values are more important than the iteration mechanism.

Do you still want chained return values in Mockito?

Cheers,
Szczepan Faber


2008/3/3 Bartosz Bankowski <bbank...@gmail.com>:

Bartosz Bańkowski

unread,
Mar 3, 2008, 9:30:01 AM3/3/08
to moc...@googlegroups.com
I haven't tried ResultSetBuilder. It requires to write some additional
code, but it definitely looks a lot better than the first snippet of
code.

> Do you still want chained return values in Mockito?

No and I don't have anything more to show you :) I will try your
solution next time!

Thanks,
Bartosz

2008/3/3 szczepiq <szcz...@gmail.com>:

Reply all
Reply to author
Forward
0 new messages