Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking with different responses for consecutive calls

I am testing filter method which takes list as input and calls another method(which returns boolean) for each item in list, and counts number of eligible items.

Mockito.doReturn(valid)
                .doReturn(inValid)
                .doReturn(valid)
                .doReturn(inValid)
                .doReturn(valid)
                .when(mySpy).isEligible(
                any(Item.class),anyString());

This used to work when method to be tested was calling isEligible in for loop

public int filter(List<Item> items){
    int count=0;
    for(i=0;i<items.size;i++){
        if(isEligible(items.get(i)))
           count++;
    return count;
}

Now I changed it to use java streams

public int filter(List<Item> items){
    items.stream().filter(item -> isEligible(item));
    return items.size;
}

Now my mock is not working, real method is getting called

like image 380
Karthik YR Avatar asked Aug 31 '25 01:08

Karthik YR


1 Answers

Stubbing consecutive calls (iterator-style stubbing) Use thenReturn for consecutive stubbing

Sometimes we need to stub with different return value/exception for the same method call. Typical use case could be mocking iterators. Original version of Mockito did not have this feature to promote simple mocking. For example, instead of iterators one could use Iterable or simply collections. Those offer natural ways of stubbing (e.g. using real collections). In rare scenarios stubbing consecutive calls could be useful, though:

 when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");

  //First call: throws runtime exception:
  mock.someMethod("some arg");

  //Second call: prints "foo"
   System.out.println(mock.someMethod("some arg"));

  //Any consecutive call: prints "foo" as well (last stubbing wins).
  System.out.println(mock.someMethod("some arg"));

Alternative, shorter version of consecutive stubbing:

when(mock.someMethod("some arg"))
.thenReturn("one", "two", "three");

In your case

Mockito.mock(mySpy.isEligible(any(Item.class))).thenReturn(true,false,false,true);
like image 87
Deadpool Avatar answered Sep 05 '25 21:09

Deadpool