简体   繁体   中英

How do I verify a call is made on a specific list in my method?

If I have the following code:

public void process(List<String> messages){
    
    Map<String, List<String>> mapofLists = new HashMap<>();
    List<String> list1 = new ArrayList();
    List<String> list2 = new ArrayList();
    List<String> list3 = new ArrayList();    

    for (String message : messages) {
        if(message.contains("123")){
            list.add(message);
        }
        else if(message.contains("456")) {
            list2.add(message);
        }
        else {
            list3.add(message);
        }
    }

    mapofLists.put("123",list1);
    mapofLists.put("345",list2);
    mapofLists.put("678",list3);

    service.makeApiCall(mapofLists);

}

I know how to verify the api call at the end. But I am confused on how I can write a test to make sure each list (list1,list2,list3) has the right amount of messages added, based on the messages list passed in. How would I do this?

Mockito to my knowledge does not allow you to expose and mock the internals of a method like this. If you were passing the mapOfLists or the individual lists into the process method you would be able to do this fairly easily using the same or similar methods you used to verify the call to the service method; however, for this method that does not make much sense as the user would need to create each value before hand, and if you decide to change how many lists you need that would be troublesome down the road.

Probably the best way is to move the api call out of the process method, and return the mapOfLists to be sent using the service later. You can use your various asserts on the map to ensure the right data is being sent out.

This will also allow you to decouple the two actions so that processing and sending are truly 2 separate actions rather than 1 making your code more maintainable and readable.

public class Processor {
    public static Map<String, List<String>> processor(List<String> message) {
        Map<String, List<String>> mapOfLists = new HashMap<>();

        List<String> list1 = new ArrayList();
        List<String> list2 = new ArrayList();
        List<String> list3 = new ArrayList();    

        for (String message : messages) {
            if(message.contains("123")) {
                list.add(message);
            } else if(message.contains("456")) {
                list2.add(message);
            } else {
                list3.add(message);
            }
        }

        mapOfLists.put("123",list1);
        mapOfLists.put("345",list2);
        mapOfLists.put("678",list3);

        return mapOfLists;
    }
}

and in your test file

public class TestProcessing {
    @Test
    public void testEmpty() {
        List<String> messages = new ArrayList<>();

        Map<String, List<String>> expected = new HashMap<>();
        expected.put("123", new ArrayList<>();
        expected.put("345", new ArrayList<>();
        expected.put("678", new ArrayList<>();

        assertEquals(Processor.process(messages), expected);
    }
}

You could use ArgumentCaptor to intercept the argument of the API call, and then verify appropriate amounts of messages in the lists and/or the entire contents of the map, its key set and values as necessary.

Example test may look as shown below (not tested):

@Mock
ApiService service; // mock makeApiCall

@InjectMocks
ProcessService processService; // implements process(List<String messages>)

@Test
void processOk() {
    ArgumentCaptor<Map<String, List<String>>> captor = ArgumentCaptor.forClass(Map.class);

    doNothing().when(service).makeApiCall(any());

    processService.process(List.of("123", "456_1", "456_2", "Test"));
    verify(service, times(1)).makeApiCall(captor.capture());

    Map<String, List<String>> map = captor.getValue();
    
    assertEquals(3, map.size());
    assertEquals(1, map.get("123"));
    assertEquals(2, map.get("345"));
    assertEquals(1, map.get("678"));
}

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