Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic chaining "thenReturn" in mockito

I have a Tuple mock class, whose getString(0) and getString(1) methods are expected to be called n times. Instead of writing something like,

when(tuple.getString(0)).thenReturn(logEntries[0]).thenReturn(logEntries[1])...thenReturn(logEntries[n - 1])

manually, I tried the following:

OngoingStubbing stubbingGetStringZero = when(tuple.getString(0)).thenReturn(serviceRequestKey);
OngoingStubbing stubbingGetStringOne = when(tuple.getString(1)).thenReturn(logEntries[0]);
for (int i = 1; i < n; i++) {
    stubbingGetStringZero = stubbingGetStringZero.thenReturn(serviceRequestKey);
    stubbingGetStringOne = stubbingGetStringOne.thenReturn(logEntries[i]);
}

The expected result is that all calls to tuple.getString(0) should return the String serviceRequestKey and each call to tuple.getString(1) should return a different String logEntries[i] ie. ith invocation of tuple.getString(1) returns ith element of logEntries array.

However, due to some odd reason, things are getting mixed up, and second invocation to tuple.getString(1) returns the String serviceRequestKey instead of logEntries[1]. What am I missing here?

like image 972
gjain Avatar asked Jul 29 '14 07:07

gjain


People also ask

What does thenReturn do in Mockito?

The thenReturn() methods lets you define the return value when a particular method of the mocked object is been called.

What is the difference between doReturn and thenReturn in Mockito?

One thing that when/thenReturn gives you, that doReturn/when doesn't, is type-checking of the value that you're returning, at compile time. However, I believe this is of almost no value - if you've got the type wrong, you'll find out as soon as you run your test. I strongly recommend only using doReturn/when .

What is Returns_deep_stubs?

RETURNS_DEEP_STUBS. An answer that returns deep stubs (not mocks). RETURNS_DEFAULTS. The default configured answer of every mock.


2 Answers

Well, the right way to do this would be:

import org.mockito.AdditionalAnswers;

String[] logEntry = // Some initialization code
List<String> logEntryList = Arrays.asList(logEntry);
when(tuple.getString(1)).thenAnswer(AdditionalAnswers.returnsElementsOf(logEntryList));

On each invocation, successive elements of logEntry array are returned. Thus, ith invocation of tuple.getString(1) returns ith element of logEntry array.

P.S: The example in documentation of returnsElementsOf (as of this writing) is not updated (it still uses ReturnsElementsOf example): http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/AdditionalAnswers.html#returnsElementsOf(java.util.Collection)it

like image 198
gjain Avatar answered Sep 28 '22 03:09

gjain


If I understood well, you want your mock to return different results depending on the invocation (meaning result1 when invoked for the first time, result2 when invoked for the second time etc)- this can be accomplished with such thing

Mockito.when(tuple.getString(0)).thenReturn(serviceRequestKey,logEntries[0],logEntries[1])

With this you will get serviceRequestKey on first invocation, logEntries[0] on second etc...

If you want something more sophisticated, like change the return depending on the param in the method use thenAnswer() as shown here

like image 20
Nadir Avatar answered Sep 28 '22 02:09

Nadir