2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Mockito] 3.2.4 → 3.3.xにアップデートしたら(イケテナイところが)エラーになった件

Posted at

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:

ざっと調べた範囲で見つけた抑止方法なので、他にももっとよい方法があるかもしれません!!

@Mocklenient 属性の利用

アノテーションを利用してモックオブジェクトを生成している場合、アノテーションの属性指定で抑止可能です。

// @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編: @MockitoSettingsstrictness 属性の利用

JUnit 5(MockitoExtension)を利用している場合は、@MockitoSettings アノテーションの属性指定で抑止可能です。
この設定は、Mockito#mock メソッドを使用している部分にも適用されるみたいです。

@MockitoSettings(strictness = Strictness.LENIENT) // これを追加
@ExtendWith(MockitoExtension.class)
abstract class BaseTypeHandlerTest {
  // ...
  @Mock
  protected PreparedStatement ps;
  // ...
}

NOTE:

本エントリでは触れませんが、JUnit 4でも同様のオプションが用意されているみたいです。

まとめ

Mickitoは単体テストの前提を整えるのに非常に便利なライブラリですが、それらのコードをクリーンな状態を保たないと後から見た時に「これ何やってるんだっけ?」みたいな状態になりがちなので・・・こういったチェック機構はありがたいですね(直し方がわからない時がたまにありますが・・・:sweat_smile:)。
ただ・・・ライブラリのレポート内容が絶対的に正しいとは限らないので、レポート内容とコードを見極めたうえで、必要に応じて「lenient」モードの利用も検討するとよいと思います。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?