简体   繁体   中英

How to mock a method which is called twice and argument of second method call is output of first method call using Mockito

public List<Object> getDummyData(String testString ) {      
    final List<String> result1 = utility.getData(testString);
    final List<String> result2 = utility.getData(result1.get(0).split(~)[0]);       
    // Processing of result2 and few more method calls      
    return someListOfObject;
}

I need to mock the method having above method calls. When I go with below code:

MainApp mock= Mockito.mock(MainApp.class);
List<String> mockList = Mockito.mock(ArrayList.class);
doReturn(mockList).when(mock).getData("str");

I am getting IndexOutOfBoundsException while running the test case at second method call.

The reason for that exception is that line:

 utility.getData(result1.get(0).split(~)[0]);

You want to split on the result from your first call. But you didn't specify anything about that mock! And when you don't specify anything, then mockito will just return dummy/empty/null data when methods are called on that mock.

And you don't have to. You absolutely do not mock a list object. You simply create a list that fits your test; like

List<String> dummyList = Arrays.asList("whatever", "strings", "you need");

Just to make that very clear: mocking is your last resort. You only use it in order to get control over objects you need to control; and that can't be controlled any other way.

And a list is super-easy to control: by creating a list that contains what you need to be in that list.

The other part of your question: you can instruct Mockito easily to return different results when the same method is called repeatedly; for example like shown here .

The reason you are getting an error is that Mockito.mock(ArrayList.class) has not values so when get(0) you get the IndexOutOfBoundsException .

Instead you should be putting data in a real list.

MainApp mock= Mockito.mock(MainApp.class);
List<String> resultA = Arrays.asList("some~value", "some~other~value");
doReturn(resultA).when(mock).getData("str");
List<String> resultB = Arrays.asList("other value", "more other values");
doReturn(resultB).when(mock).getData("some");

While the above would work I would suggest using matchers for the mocking and then verify the correct results. The reason being that you will get better error messages if the test fails.

MainApp mock= Mockito.mock(MainApp.class);

// Mock multiple return values
Mockito.when(mock.getData(anyString())
  .thenReturn(Arrays.asList("some~value", "some~other~value"))
  .thenReturn(Arrays.asList("other value", "more other values"));

List<SomeObjects> result = getDummyData("some-arg");
Mockito.verify(mock).getData("some-arg"); //Verify correct calls
Mockito.verify(mock).getData("some");

// verify result

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM