Mockito 3.2.4から3.3.x(3.3.3)にアップデートしたら・・・スタブを設定しているコードが冗長?だったことが原因でエラーになってしまいました。
どんなコードだったの?
こんなコードでした。
when(rs.getInt("column")).thenReturn(100);
assertEquals(Integer.valueOf(100), TYPE_HANDLER.getResult(rs, "column"));
when(rs.getInt("column")).thenReturn(0);
assertEquals(Integer.valueOf(0), TYPE_HANDLER.getResult(rs, "column"));
どんなエラーになったの?
こんなエラーです。
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
There are 1 unnecessary stubbing (click to navigate to relevant line of code):
1. -> at org.apache.ibatis.type.YearTypeHandlerTest.shouldGetResultFromResultSetByName(YearTypeHandlerTest.java:44)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
何がイケテナイの?
どうやら・・・thenReturn
のところがイケテナイようで、以下のようにしたらエラーがなくなりました。
when(rs.getInt("column")).thenReturn(100, 0); // 一箇所に集約!!
assertEquals(Integer.valueOf(100), TYPE_HANDLER.getResult(rs, "column"));
assertEquals(Integer.valueOf(0), TYPE_HANDLER.getResult(rs, "column"));
まーね・・・という感じです。
コードを直さないとダメなの?
明確な意図がない場合は基本的にはコードを直した方がよいと思いますが、エラーメッセージにも記載があるように「lenient」モードにすることでこのエラーを抑止することができます。以下に、抑止する方法をいくつか紹介します。
NOTE:
ざっと調べた範囲で見つけた抑止方法なので、他にももっとよい方法があるかもしれません!!
@Mock
の lenient
属性の利用
アノテーションを利用してモックオブジェクトを生成している場合、アノテーションの属性指定で抑止可能です。
// @Mock
@Mock(lenient = true)
protected ResultSet rs;
MockSettings#lenient()
の利用
Mockito#mock
メソッドを利用してモックオブジェクトを生成している場合は、メソッドのオプション指定で抑止可能です。
// ResultSet rs = mock(ResultSet.class);
ResultSet rs = mock(ResultSet.class, withSettings().lenient());
when(rs.getInt("column")).thenReturn(INSTANT.getValue());
assertEquals(INSTANT, TYPE_HANDLER.getResult(rs, "column"));
when(rs.getInt("column")).thenReturn(0);
assertEquals(Year.of(0), TYPE_HANDLER.getResult(rs, "column"));
Mockito.lenient()
の利用
Mockito.lenient()
を使用して抑止することもできますが、この方法で抑止するくらいなら、ちゃんと直しちゃった方がよいでしょう。
// when(rs.getInt("column")).thenReturn(100);
lenient().when(rs.getInt("column")).thenReturn(100);
// ...
JUnit 5編: @MockitoSettings
の strictness
属性の利用
JUnit 5(MockitoExtension
)を利用している場合は、@MockitoSettings
アノテーションの属性指定で抑止可能です。
この設定は、Mockito#mock
メソッドを使用している部分にも適用されるみたいです。
@MockitoSettings(strictness = Strictness.LENIENT) // これを追加
@ExtendWith(MockitoExtension.class)
abstract class BaseTypeHandlerTest {
// ...
@Mock
protected PreparedStatement ps;
// ...
}
NOTE:
本エントリでは触れませんが、JUnit 4でも同様のオプションが用意されているみたいです。
まとめ
Mickitoは単体テストの前提を整えるのに非常に便利なライブラリですが、それらのコードをクリーンな状態を保たないと後から見た時に「これ何やってるんだっけ?」みたいな状態になりがちなので・・・こういったチェック機構はありがたいですね(直し方がわからない時がたまにありますが・・・)。
ただ・・・ライブラリのレポート内容が絶対的に正しいとは限らないので、レポート内容とコードを見極めたうえで、必要に応じて「lenient」モードの利用も検討するとよいと思います。