ArgumentMatcherとは
テストにおいて、メソッドの動作設定とメソッド呼び出し検証でモックに渡す引数と、実際にテスト対象クラスからモックのメソッドに渡される引数は異なる可能性がある。
この時、ArgumentMatcherを使うことで、引数の中身をふわっと検証できる。
- 渡される型のみ検証する
- 他のテストケースで検証済みの引数の検証を省略する
- 細かい条件を指定する
などの使い道がある。
例えば、渡される型のみ検証したい場合はArgumentMatchers.anyメソッドが利用可能。
また、すでに他のテストケースで検証済みの引数の検証をスキップするのにも使われる。
Mockito.doNothing().when(display).display(ArgumentMatchers.any());
Mockito.verify(display, Mockito.times(1)).display(ArgumentMatchers.any());
基本型やコレクション型の一部はあらかじめ対応するanyメソッドがあるが、自作クラスの型を検証するときは作成することもできる。
Mockito.doNothing().when(display).display(ArgumentMatchers.anyString());
Mockito.verify(display, Mockito.times(1)).display(ArgumentMatchers.any(String.class));
細かい条件を指定したいとき
- ArgumentMatcherインターフェースの実装クラスを作成する。このとき、matchesメソッドをオーバーライドする。
- メソッドの動作設定とメソッド呼び出し検証で、MockitoクラスのargThatメソッドの引数に上記のクラスのインスタンスを渡す。
ArgumentMatcher<String> matcher = argument -> {
assertThat(argument.substring(1), is(msg));
return true;
};
Mockito.doNothing().when(display).display(Mockito.argThat(matcher));
Mockito.verify(display, Mockito.times(1)).display(Mockito.argThat(matcher));
注意
上記の式にはラムダ式が使われている。
ラムダ式は匿名クラスによる記述をさらに省略したもの。
ArgumentMatcherのmatchesメソッドのオーバーライドを匿名クラスを使って書くと以下の通り。
ArgumentMatcher<String> matcher = new ArgumentMatcher(
@Override
public boolean matches(Object argument) {
assertThat(argument.substring(1), is(msg));
return true;
}
)
ラムダ式を用いることで以下のことができる
- new を省略 (ラムダ式では必ずインスタンスを作成するため)
- ArgumentMatcher を省略 (ここで、matcherに渡したいのはArgumentMatcherの実装クラスだから,明らか。多分変数の型宣言がここで効いてる)
- @Override, matchesを省略 (ArgumentMatcherインターフェースはメソッドが1つしかない。これの実装クラスを作るので、どちらも明らか。)
練習のために、今一度ArgumentMatcherの定義を書いてみる。
ArgumentMatcher<String> matcher = argument -> {
assertThat(argument.substring(1), is(msg));
return true;
};
よくできました。