[JAVA] Check with Mockito whether Method was called when Map → List (when, verify)

You can check if the Stub method is called with a fixed argument by using Mockito's verify, but when using Map it will be random and will not work with normal verify. Validate the arguments using argThat of ArgumentMatcher.

Maven Add Dependency to pom.xml so that you can use ArgumentMatcher's argThat.

For example ... </ u> </ font>

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor //Autowired God Repository without using a constructor
public class GodServiceImpl implements GodService {

  private final GodRepository godRepository; //Final when using RequiredArgsConstructor

  @Override
  public void update(Map map) {
    List<String> updateList = new ArrayList<>(map.keySet()); //List in random order
    godRepository.update(updateList);
  }
}

Create a test of

import static java.util.Arrays.asList;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class) //Omit necessary settings, etc.
class GodServiceImplTest {

  private GodService godService;

  @Mock
  private GodRepository godRepository;

  @BeforeEach
  public void setUp() {
    godService = new GodServiceImpl(godRepository); //Inject the Mocked God Repository
  }

  @Test
  void update() {
    when(godRepository.update(asList("2a", "3b", "1c", "4d"))).thenReturn(4);

    Map<String, String> updateMap = new HashMap<>();
    updateMap.put("2a", "1");
    updateMap.put("3b", "2");
    updateMap.put("1c", "3");
    updateMap.put("4d", "4");
    godService.update(updateMap);

    verify(godRepository).update(asList("2a", "3b", "1c", "4d"));
  }
}

When you run the test

org.mockito.exceptions.misusing.PotentialStubbingProblem: 
Strict stubbing argument mismatch. Please check:
 - this invocation of 'update' method:
    godRepository.update([4d, 1c, 2a, 3b]);

It is said that the order of the arguments is different.

ArgumentMatcher Therefore, argument validation is also performed using argThat of ArgumentMatcher.

import static java.util.Arrays.asList;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class) //Omit necessary settings, etc.
class GodServiceImplTest {

  private GodService godService;

  @Mock
  private GodRepository godRepository;

  @BeforeEach
  public void setUp() {
    godService = new GodServiceImpl(godRepository); //Inject the Mocked God Repository
  }

  @Test
  void update() {
    //If only containsAll, even 3 arguments will pass, so avoid it with size
    when(godRepository.update(argThat(list -> list.size() == 4 &&
        list.containsAll(asList("2a", "3b", "1c", "4d"))))).thenReturn(4);

    Map<String, String> updateMap = new HashMap<>();
    updateMap.put("2a", "1");
    updateMap.put("3b", "2");
    updateMap.put("1c", "3");
    updateMap.put("4d", "4");
    godService.update(updateMap);

    verify(godRepository).update(argThat(list -> list.size() == 4 &&
        list.containsAll(asList("2a", "3b", "1c", "4d"))));
  }
}

Recommended Posts