stub(mockedList).toReturn("first").on().get(0);
instead of:
stub(mockedList.get(0)).toReturn("first");
--
Pedro Pedruzzi | V2COM
>> 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.
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
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
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...
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
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
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
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.
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