Stubにしたメソッドが決められた引数で呼ばれているのかをMockitoのverifyを使うことで確認することができるが、Mapを使用しているときはランダムになるため普通のverifyでは通用しなくなるのでArgumentMatcherのargThatを使用して引数の検証を行う。
Maven
ArgumentMatcherのargThatを使用できるように、Dependencyをpom.xmlに追加しておく。
例えば...
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor // コンストラクタを使用せずにGodRepositoryをAutowiredする
public class GodServiceImpl implements GodService {
private final GodRepository godRepository; // RequiredArgsConstructorを使用する時はfinalにする
@Override
public void update(Map map) {
List<String> updateList = new ArrayList<>(map.keySet()); // 順番がランダムなListになる
godRepository.update(updateList);
}
}
のテストを以下のように作成して
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) // 必要な設定等省略する
class GodServiceImplTest {
private GodService godService;
@Mock
private GodRepository godRepository;
@BeforeEach
public void setUp() {
godService = new GodServiceImpl(godRepository); // MockしたGodRepositoryをInjectする
}
@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"));
}
}
テストを実行すると
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'update' method:
godRepository.update([4d, 1c, 2a, 3b]);
引数の順番が違うと言われる。
ArgumentMatcher
そこでArgumentMatcherのargThatを使用して引数の検証も行う。
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) // 必要な設定等省略する
class GodServiceImplTest {
private GodService godService;
@Mock
private GodRepository godRepository;
@BeforeEach
public void setUp() {
godService = new GodServiceImpl(godRepository); // MockしたGodRepositoryをInjectする
}
@Test
void update() {
// containsAllだけでは引数が3つでも通過してしまうので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"))));
}
}