Mockito Strict StubbingとUnnecessaryStubbingException

  • link:/category/testing/ [テスト]

  • Mockito

1. 概要

*このクイックチュートリアルでは、Mockito _UnnecessaryStubbingException_ *について学習します。 この例外は、スタブの不適切な使用時に発生する可能性が高い一般的な例外の1つです。
厳密なスタブの背後にある哲学と、Mockitoがデフォルトでその使用を推奨する理由を説明することから始めます。 次に、この例外が何を意味し、どのような状況で発生する可能性があるのか​​を詳しく見ていきます。 最後に、テストでこの例外を抑制する方法の例を示します。
Mockitoでのテストの詳細については、包括的なlink:/tag/mockito/[Mockitoシリーズ]をご覧ください。

2. 厳密なスタビング

Mockitoのバージョン1.xでは、種類の制限なしにモックを設定および操作できました。 これは、時間の経過とともに、テス​​トがしばしば複雑になり、時にはデバッグが難しくなることを意味していました。
バージョン2. +以降、* Mockitoはフレームワークを「厳格」に近づける新しい機能を導入しています。*この背後にある主な目標は次のとおりです。

*
* テストコードの重複と削減
* 「デッド」コードを削除して、よりクリーンなテストを促進する
* デバッグ性と生産性の向上を支援

*これらの原則に従うと、不要なテストコードを削除して、よりクリーンなテストを作成できます*。 また、他の開発者の見落としと同様に、コピーアンドペーストエラーを回避するのにも役立ちます。
要約すると、厳密なスタブは不必要なスタブを報告し、スタブ引数の不一致を検出し、テストをよりDRY(Do n't Repeat Yourself)にします。 これにより、

* 2.1。 厳密なスタブの構成*

Mockito 2. +以降では、次のいずれかを使用してモックを初期化するときに、厳密なスタブがデフォルトで使用されます。
  • _ MockitoJUnitRunner _

  • MockitoJUnit.rule()

  • Mockitoは上記のいずれかを使用することを強くお勧めします*。 ただし、Mockitoルールまたはランナーを活用していない場合、テストで厳密なスタブを有効にする別の方法もあります。

Mockito.mockitoSession()
  .initMocks(this)
  .strictness(Strictness.STRICT_STUBS)
  .startMocking();
*最後の重要なポイントは、Mockito 3.0では、すべてのスタブがデフォルトで「厳格」で検証されることです。*

3. _UnnecessaryStubbingException_例

*簡単に言えば、不要なスタブは、テスト実行中に実現されなかったスタブ化されたメソッド呼び出しです。*
簡単な例を見てみましょう。
@Test
public void givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException() {
    when(mockList.add("one")).thenReturn(true); // this won't get called
    when(mockList.get(anyInt())).thenReturn("hello");
    assertEquals("List should contain hello", "hello", mockList.get(1));
}
この単体テストを実行すると、Mockitoは未使用のスタブを検出し、_UnnecessaryStubbingException_をスローします。
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at com.baeldung.mockito.misusing.MockitoUnecessaryStubUnitTest.givenUnusedStub_whenInvokingGetThenThrowUnnecessaryStubbingException(MockitoUnecessaryStubUnitTest.java:37)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
ありがたいことに、エラーメッセージから、ここに問題が何であるかが明確にわかります。 また、例外メッセージがエラーの原因となっている正確な行を示していることもわかります。
なぜこれが起こるのですか? さて、最初の_when_呼び出しは、引数_“ one” _で_add_メソッドを呼び出すときに_true_を返すようにモックを構成します。 ただし、ユニットテストの残りの実行中はこのメソッドを呼び出しません。
  • Mockitoは、最初の_when_行が冗長であり、おそらくスタブの構成時にエラーが発生したことを示しています。*

    この例は簡単ですが、オブジェクトの複雑な階層をモックするとき、この種のメッセージがどのようにデバッグを助け、他の方法で非常に役立つか想像するのは簡単です。

4. 厳密なスタビングのバイパス

*最後に、厳密なスタブをバイパスする方法を見てみましょう。*これは、寛大なスタブとしても知られています。
厳密なスタブを使用するために、他のすべてのスタブとモックを維持しながら、特定のスタブを緩やかに設定する必要がある場合があります。
@Test
public void givenLenientdStub_whenInvokingGetThenThrowUnnecessaryStubbingException() {
    lenient().when(mockList.add("one")).thenReturn(true);
    when(mockList.get(anyInt())).thenReturn("hello");
    assertEquals("List should contain hello", "hello", mockList.get(1));
}
上記の例では、*静的メソッド_Mockito.lenient()_を使用して、モックリストの_add_メソッドで寛大なスタブを有効にします。*
Lenientスタブは、「厳密なスタブ化」検証ルールをバイパスします。 たとえば、スタブが寛大であると宣言された場合、前述の不要なスタブなどの潜在的なスタブの問題についてはチェックされません。

5. 結論

この短い記事では、Mockitoで厳密なスタブの概念を紹介することから始め、それがなぜ導入され、なぜ重要なのかという哲学を理解しました。
次に、テストで寛大なスタブを有効にする方法の例を終了する前に、_UnnecessaryStubbingException_の例を見てみました。
いつものように、記事の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/testing-modules/mockito-2[GitHub]で入手できます。