1. 概要

このクイックチュートリアルでは、MockitoUnnecessaryStubbingExceptionについて学習します。 この例外は、スタブを誤って使用した場合に発生する可能性のある一般的な例外です。

まず、厳密なスタブの背後にある哲学と、Mockitoがデフォルトでその使用を推奨する理由を説明します。 次に、この例外が何を意味し、どのような状況で発生する可能性があるかを正確に見ていきます。 最後に、テストでこの例外を抑制する方法の例を示します。

Mockitoを使用したテストの詳細については、包括的なMockitoシリーズをご覧ください。

2. 厳格なスタブ

Mockitoのバージョン1.xでは、制限なしでモックを構成して操作することができました。 これは、時間の経過とともに、テストが複雑になりすぎ、デバッグが困難になる場合があることを意味しました。

バージョン2.+以降、 Mockitoは、フレームワークを「厳密さ」に近づける新機能を導入しています。この背後にある主な目標は次のとおりです。

  • テストコードで未使用のスタブを検出する
  • テストコードの重複を減らし、u必要なテストコード
  • 「デッド」コードを削除して、よりクリーンなテストを促進する
  • デバッグ可能性と生産性の向上に役立ちます

これらの原則に従うと、不要なテストコードを排除して、よりクリーンなテストを作成できます。 また、コピーと貼り付けのエラーやその他の開発者の見落としを回避するのにも役立ちます。

要約すると、厳密なスタブは不要なスタブを報告し、スタブ引数の不一致を検出し、テストをよりドライにします(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メソッドで寛大なスタブを有効にします。

寛大なスタブは、「厳密なスタブ」検証ルールをバイパスします。 たとえば、スタブが寛大であると宣言されている場合、前述の不要なスタブなど、潜在的なスタブの問題がないかどうかはチェックされません。

5. 結論

この短い記事では、Mockitoでの厳密なスタブの概念を紹介し、それが導入された理由とそれが重要である理由の背後にある哲学を詳しく説明しました。

次に、 UnnecessaryStubbingException、の例を見てから、テストで寛大なスタブを有効にする方法の例を終了しました。

いつものように、記事の完全なソースコードはGitHubで入手できます。