3

Normally with Mockito, if you're stubbing a method that gets called multiple times, you'd do

Mockito
    .doReturn(0)
    .doReturn(1)
    .doReturn(2)
    .when(mock).getValue();

I'd like to programaitcally stub a method that gets called multiple times, something like

Stubber stubber;
for (int i = 0; i < 8; ++i) {
    stubber.doReturn(i);
}
stubber.when(mock).getValue();

My problem is there doesn't seem to be a public Stubber factory method. There's org.mockito.internal.MockitoCore.stubber() and new org.mockito.internal.stubbing.StubberImpl(), but both are internal, and using them feels wrong.

Is there a better pattern for programatically stubbing like this? Is there a better way to get an empty Stubber?

One solution would be when().thenReturn(), but I've been avoiding that since reading on the difference between doReturn() and then().

Community
  • 1
  • 1
David Ehrmann
  • 7,366
  • 2
  • 31
  • 40

1 Answers1

2

The only official way to get a Stubber is to call doReturn or doAnswer (etc).

The better pattern for stubbing like that is to use returnsElementsOf:

List<Integer> returnValues = new ArrayList<>();
for (int i = 0; i < 8; ++i) {
    returnValues.add(i);
}
doAnswer(returnsElementsOf(returnValues)).when(mock).getValue();

You can also pass in an Array into doReturn, which already takes an array-compatible varargs, but only as its two-parameter overload:

int[] returnValues = new int[7];
for (int i = 1; i < 8; ++i) {
    returnValues[i] = i;
}
doReturn(0, returnValues).when(mock).getValue();
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • I've tried this with a spy object and it only works for `doAnswer` on void methods but not for `doReturn` on non-void methods. Is it just me or can you confirm this? – jansohn Mar 07 '18 at 22:05
  • 1
    @lazlev Well, I made a silly mistake and swapped `doReturn` and `doAnswer`, so let me fix that first. What behavior do you see in the errant `doReturn` case you mentioned? – Jeff Bowman Mar 07 '18 at 22:08
  • I'm getting `org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ReturnsElementsOf cannot be returned by methodName()`. I'm sending in a list of strings as the method I'm mocking is returning a string. – jansohn Mar 07 '18 at 22:13
  • OK, swapping `doReturn` to `doAnswer` fixed the error I was mentioning. I also tried using `returnsElementsOf` with a list of `Answer` to dynamically mock the behavior of a void method. Unfortunately this is not working and fails silently... – jansohn Mar 07 '18 at 22:35