19

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?

gjain
  • 4,468
  • 5
  • 39
  • 47

4 Answers4

23

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

gjain
  • 4,468
  • 5
  • 39
  • 47
6

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

Community
  • 1
  • 1
Nadir
  • 1,369
  • 1
  • 15
  • 28
  • Well, your answer is correct and essentially a shorthand version of multiple thenReturn. The only thing is the number of invocations in my case is a bit large ~ 15-20. So, I will have to write that many parameters for thenReturn. Was hoping to find a solution using a for loop or something. – gjain Jul 29 '14 at 09:10
  • thenReturn method acceps the String[], so you can create the array in the loop as you wanted and pass it then. – Nadir Jul 29 '14 at 09:33
  • thenReturn() only accepts multiple String parameters, not an array. See: http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html. Anyway, your comment helped me look in the right direction. Thanks! – gjain Jul 29 '14 at 10:23
  • 1
    @gjain, varargs are just syntactic sugar on top of arrays, so String[] would work well. See http://stackoverflow.com/questions/2925153/can-i-pass-an-array-as-arguments-to-a-method-with-variable-arguments-in-java for more details. – Mikael Ohlson Mar 19 '15 at 11:57
  • 1
    @MikaelOhlson Problem is that you need to go on a long walk with Mockito's syntax because you need to cut the first argument off the array in order to fit: thenReturn(T value, T... values), then subList, and it's a mess. – deworde May 07 '15 at 08:28
-1

Not sure I understand Mockito well enough to understand your example, but wouldn't you want something like:

Mockito.when(tuple.getString(0)).thenReturn(serviceRequestKey);
for(int i = 0;i < logEntries.length;i++) {
    Mockito.when(tuple.getString(i+1)).thenReturn(logEntries[i]);
}
The F
  • 42
  • 2
  • I have clarified the question further. Actually, I want different result from each invocation of tuple.getString(1). Note that it is always tuple.getString(1), the index does not change. – gjain Jul 29 '14 at 08:58
-1

I know that post is older, but maybe it helps:

    OngoingStubbing<Boolean> whenCollectionHasNext = when(mockCollectionStream.hasNext());
    for (int i = 0; i < 2; i++) {
        whenCollectionHasNext = whenCollectionHasNext.thenReturn(true);
    }
    whenCollectionHasNext = whenCollectionHasNext.thenReturn(false);
Michael Hegner
  • 5,555
  • 9
  • 38
  • 64
  • This doesn't work. Here is the error message: "You probably stored a reference to OngoingStubbing returned by when() and called stubbing methods like thenReturn() on this reference more than once." – Younes El Ouarti Dec 09 '19 at 12:26