Stubbing without executing

68 views
Skip to first unread message

Pedro Pedruzzi

unread,
Jun 26, 2008, 2:24:00 PM6/26/08
to mockito
Hi!

I'm evaluating Mockito and I am really enjoying it.

I was wondering why don't we have a similar syntax for stub that we
have for verify ?

I mean (based on the 'Sample stubbing' example at [1]):

stub(mockedList).get(0).toReturn("first");

instead of:

stub(mockedList.get(0)).toReturn("first");

I noticed that with Mockito there is no state in the mockup, meaning
that it is always in the execution state (no record/reply). And that
is very good because it is always ready to run and we can verify the
interactions later. But it is strange because when setting a stub we
are in fact making a method call to the mockup. Of course this is
being distinguished by the framework. I can see that by the
interaction count verification.

But, this can get quite serious in the following case: I want a mockup
list to return "first" to the get(0) call, and to throw
IndexOutOfBoundsException otherwise.

stub(mockedList.get(anyInt())).toThrow(new
IndexOutOfBoundsException());
stub(mockedList.get(0)).toReturn("first");

My stub exception is thrown in the second line. I did not want to call
the get method. I just want to stub it!

Am doing something completely wrong?

Regards,

--
Pedro Pedruzzi | V2COM

[1] http://code.google.com/p/mockito/

Pedro Pedruzzi

unread,
Jun 26, 2008, 3:30:27 PM6/26/08
to mockito
Actualy it would be a similar syntax to stubVoid method:

stub(mockedList).toReturn("first").on().get(0);

instead of:

stub(mockedList.get(0)).toReturn("first");

--
Pedro Pedruzzi | V2COM

Kris

unread,
Jun 27, 2008, 3:20:59 AM6/27/08
to mockito
> Actualy it would be a similar syntax to stubVoid method:
> stub(mockedList).toReturn("first").on().get(0);

Hi Pedro,

(szczepiq correct me if I'm wrong)
I don't think that would solve your problem.
Consider: stubVoid(mock).toThrow(new RuntimeException).on.method();
This notation is needed because you can't write stub(mock.method())
since the return type of method() is void.
But the actual method() is in fact called on mock. If you check out
the implementation of stubVoid(), toThrow() and on(), you will notice
that the result of on() is in fact your mock.

So, if we project that to your suggestion, the result of on() in
"stub(mockedList).toReturn("first").on().get(0);" will be mockedList.
So the netto effect would be exactly the same as with the current
notation. You would still get the exception.

Kind regards,

Kris

Pedro Pedruzzi

unread,
Jun 27, 2008, 8:27:22 AM6/27/08
to moc...@googlegroups.com
Hi Kris.

>> Actualy it would be a similar syntax to stubVoid method:
>> stub(mockedList).toReturn("first").on().get(0);
>
> Hi Pedro,
>
> (szczepiq correct me if I'm wrong)
> I don't think that would solve your problem.
> Consider: stubVoid(mock).toThrow(new RuntimeException).on.method();
> This notation is needed because you can't write stub(mock.method())
> since the return type of method() is void.
> But the actual method() is in fact called on mock. If you check out
> the implementation of stubVoid(), toThrow() and on(), you will notice
> that the result of on() is in fact your mock.

Just noticed.

> So, if we project that to your suggestion, the result of on() in
> "stub(mockedList).toReturn("first").on().get(0);" will be mockedList.
> So the netto effect would be exactly the same as with the current
> notation. You would still get the exception.

That is true. But it is an implementation detail. There may be other
ways to do this without returning the mock in on() calls.

The point is that a mockito mockup cannot distinguish (on-the-fly)
weather it is been called by setup code setting a stub or by the test
routine (when it should act like a mockup). It would be very useful if
one could set a stub without the need to call the method on the mock.

One of the most intersting principles of Mockito is: "last stubbing is
more important". This allows one to do some stubbing overload:

stub(mockedList.get(anyInt())).toReturn("dummy");
stub(mockedList.get(0)).toReturn("first");

But one can not do this:

stub(mockedList.get(anyInt())).toThrow(new RuntimeException());
stub(mockedList.get(0)).toReturn("first");

Thanks for your time.

Pedro Pedruzzi

unread,
Jun 27, 2008, 10:36:32 AM6/27/08
to moc...@googlegroups.com
I've just noticed a very nice thing.

The test case:

List<String> mockedList = mock(List.class);
stub(mockedList.get(0)).toReturn("first");
stub(mockedList.get(1)).toThrow(new IndexOutOfBoundsException());

System.out.println(mockedList.get(0));
try {
System.out.println(mockedList.get(1));
} catch (Exception e) {
System.out.println("caught it!");
}
System.out.println(mockedList.get(999));

verify(mockedList).get(1);

The nice thing is that, although verify() returns the mock, the get(1)
method does not throw the stubbed exception. That is obviously because
the verify() method put the mock in a state that it knows the next
method call will be a verify case.

The same ideia could be applied to possibilite something like:

stub(mockedList).toReturn("first").on().get(0);

There is only a type issue with this approach. The the argument for
toReturn() could not be known at compile time. But Object could be
used. Or use some ugly syntax like:

stub(method(mockedList).get(0)).toReturn("first");

Regards,

--
Pedro Pedruzzi | V2COM

szczepiq

unread,
Jun 29, 2008, 2:47:26 PM6/29/08
to moc...@googlegroups.com
Hi,

Sorry for late answer I was offline for couple of days.

>stub(mockedList.get(anyInt())).toThrow(new RuntimeException());
>stub(mockedList.get(0)).toReturn("first");

Well spotted, you cannot do above due to the way mocking syntax is
implemented (it's somewhere in the FAQ). I was aware of this
limitation but I decided to make the syntax nice and don't worry about
this corner case (I bet you didn't find it in real code, did you? ;-).

>The nice thing is that, although verify() returns the mock, the get(1)
>method does not throw the stubbed exception.

This is true, the exception is not thrown because the mock is in
'verify' mode. As you already figured out, stubbing with a use of
slightly different syntax can solve your "exceptional" scenario :)

>stub(mockedList).toReturn("first").on().get(0);

Above proposal may be tricky because there is already stub() method
that takes any argument (e.g. Object). I wouldn't be able to
distinguish what syntax you're using: the regular one, or the one with
'on()'

I never liked stubVoid() syntax but that was the best I could think
of. The stubbing syntax I'd implement now if I did mockito again:

//regular stubbing:

when(mock.getStuff()).thenReturn("foo");
when(mock.getStuff()).thenThrow(new RuntimeException());

//for void methods and some corner cases:

doReturn("foo").when(mock).getStuff();
doThrow(new RuntimeException()).when(mock).someMethod();

//for stubbing consecutively:

when(mock.getStuff())
.thenReturn("foo")
.thenThrow(new RuntimeException());

doThrow(new RuntimeException())
.thenReturn("foo")
.when(mock).someMethod();


I proposed this syntax couple of weeks ago but received only single
feedback saying that it's rather cosmetic (which is true...). Hence I
decided not to change the API.

I would really like to change stubbing API to be as above but I need
some more feedback. Also, I need to know if I don't make users pissed
off with a lot of deprecated code to fix when the API changes get
released...

Cheers,
Szczepan Faber

Mwanji Ezana

unread,
Jun 30, 2008, 3:00:29 AM6/30/08
to moc...@googlegroups.com
I proposed this syntax couple of weeks ago but received only single
feedback saying that it's rather cosmetic (which is true...). Hence I
decided not to change the API.

I would really like to change stubbing API to be as above but I need
some more feedback.

Would a change towards this new syntax open the way for new functionality? Or at least make certain kinds of new functionality significantly easier to implement?

Also, I need to know if I don't make users pissed
off with a lot of deprecated code to fix when the API changes get
released...

I think it depends on how many users you have now and what your aims are. If you don't have too many now and are aiming for Mockito 2.0 to be the one to gain wide adoption, then it's less of an issue than if you already have a huge user base (I have no idea how big it might be).

Mwanji

szczepiq

unread,
Jun 30, 2008, 6:59:43 AM6/30/08
to moc...@googlegroups.com
> Would a change towards this new syntax open the way for new functionality?

No. It would just solve one limitation (stubbing method that was
previously stubbed with an exception).

> Or at least make certain kinds of new functionality significantly easier to
> implement?

No. I think any new functionality is easy to implement :)

Cheers,
Szczepan Faber

Pedro Pedruzzi

unread,
Jun 30, 2008, 8:06:24 AM6/30/08
to moc...@googlegroups.com
Hi Szczepan.

Thanks for your time and comments. I liked the
do[Return|Throw](x).when(mock).method() syntax.

As you and Mwanji pointed out, I don't think that single limitation
justifies changing the whole API. Unless of course, you're willing to
release a new 2.0 backwards incompatible API.

I would be happy with just an little API extension for this corner case to work!

Regards,

--
Pedro Pedruzzi | V2COM

szczepiq

unread,
Jul 2, 2008, 7:41:53 PM7/2/08
to moc...@googlegroups.com
Ok then,

How about replacing stubVoid() with this one:

do[Return|Throw|Answer](x).when(mock).method()

1. it fixes one corner case
2. it is syntactically nicer. In a way it is close to how we do
verify() so it is consistent with the API.

That would make stubVoid() deprecated for couple of releases (or forever :)

I don't think that it is a such a big deal to fix the deprecated code
since I don't think that stubbing voids occurs that often. It should
not be too much of a hassle for users.

Anyone feels bad about this API modification?

Cheers,
Szczepan Faber

On Mon, Jun 30, 2008 at 2:06 PM, Pedro Pedruzzi

Pedro Pedruzzi

unread,
Jul 3, 2008, 7:25:19 AM7/3/08
to moc...@googlegroups.com
Hi.

On Wed, Jul 2, 2008 at 8:41 PM, szczepiq <szcz...@gmail.com> wrote:
>
> Ok then,
>
> How about replacing stubVoid() with this one:
>
> do[Return|Throw|Answer](x).when(mock).method()
>
> 1. it fixes one corner case
> 2. it is syntactically nicer. In a way it is close to how we do
> verify() so it is consistent with the API.

If I understood well, this new form would apply for non-void methods
as well, and the stub() form would stay in the API. Is that correct?
If so, I think it is a nice improving. The only bad thing is the
impredictable type of x in the case of doReturn(x).

Do you pretend to deprecate stub() in the future?

> That would make stubVoid() deprecated for couple of releases (or forever :)
>
> I don't think that it is a such a big deal to fix the deprecated code
> since I don't think that stubbing voids occurs that often. It should
> not be too much of a hassle for users.
>
> Anyone feels bad about this API modification?

I don't.

szczepiq

unread,
Jul 3, 2008, 10:06:54 AM7/3/08
to moc...@googlegroups.com
> If I understood well, this new form would apply for non-void methods
> as well, and the stub() form would stay in the API. Is that correct?

You're right, the new syntax can be used also for non-void methods.
However, I wouldn't recommend it for non-voids because:

1. It doesn't force the correct return type:

doReturn("cannot determine the type here").when(mock).method()

2. It's a bit less readable than stub()

doReturn("foo").when(mock).method();

vs

stub(mock.method()).toReturn("foo");


3. It's far less readable when stubbing consecutive calls

doReturn("foo")
.thenReturn("bar")
.when(mock).method()

vs

stub(mock.method())
.toReturn("foo")
.toReturn("bar");

Hence the new syntax is a successor of stubVoid() but not stub()

> Do you pretend to deprecate stub() in the future?

No. Unless I manage to convince users to evolve into
when(mock.method()).thenReturn|thenThrow() syntax. Then the when()
syntax could replace stub() syntax. But this is completely different
story ;)

Cheers,
Szczepan Faber

burne...@googlemail.com

unread,
Jul 7, 2008, 5:32:03 PM7/7/08
to mockito
Hey Szczeps

I like the when syntax better, and it the corresponding solution for
stubVoid looks miles better.
I don't think the migration path would be that hard - if it wasn't
past my bedtime, I'd write the regular expression for it right now!

Mark
> On Thu, Jul 3, 2008 at 1:25 PM, Pedro Pedruzzi <pedro.pedru...@gmail.com> wrote:
>
> > Hi.
>

analogue

unread,
Jul 9, 2008, 12:09:33 AM7/9/08
to mockito
+1 new api
+1 for doing a python version (pockito?) -- just thought i'd throw
that in there
Reply all
Reply to author
Forward
0 new messages