私のコードは以下の通りです、
@RunWith(MockitoJUnitRunner.class)
public class MyClass {
private static final String code ="Test";
@Mock
private MyClassDAO dao;
@InjectMocks
private MyClassService Service = new MyClassServiceImpl();
@Test
public void testDoSearch() throws Exception {
final String METHOD_NAME = logger.getName().concat(".testDoSearchEcRcfInspections()");
CriteriaDTO dto = new CriteriaDTO();
dto.setCode(code);
inspectionService.searchEcRcfInspections(dto);
List<SearchCriteriaDTO> summaryList = new ArrayList<SearchCriteriaDTO>();
inspectionsSummaryList.add(dto);
when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
verify(dao).doSearchInspections(dto);
}
}
私は例外を下回っています
org.mockito.exceptions.misusing.UnnecessaryStubbingException: Unnecessary stubbings detected in test class: Test Clean & maintainable test code requires zero unnecessary code. Following stubbings are unnecessary (click to navigate to relevant line of code): 1. -> at service.Test.testDoSearch(Test.Java:72) Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class. at org.mockito.internal.exceptions.Reporter.formatUnncessaryStubbingException(Reporter.Java:838) at org.mockito.internal.junit.UnnecessaryStubbingsReporter.validateUnusedStubs(UnnecessaryStubbingsReporter.Java:34) at org.mockito.internal.runners.StrictRunner.run(StrictRunner.Java:49) at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.Java:103) at org.Eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.Java:86) at org.Eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.Java:38) at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.Java:459) at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.Java:675) at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.Java:382) at org.Eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.Java:192)
解決方法を手伝ってください
@RunWith(MockitoJUnitRunner.class)
を@RunWith(MockitoJUnitRunner.Silent.class)
に置き換えます。
最初にテストロジックを確認してください。通常3つのケースがあります。まず、あなたは間違った方法を偽造しています(あなたはタイプミスをしたか、誰かが偽造された方法がもはや使用されないようにテストされたコードを変更しました)。次に、このメソッドが呼び出される前にテストが失敗しています。第三に、/ switchがコード内のどこかに分岐してモックメソッドが呼び出されないようにすると、ロジックが間違ってしまいます。
これが最初のケースであるならば、あなたは常にコードで使われたもののためにモックされたメソッドを変えたいと思います。 2番目と3番目では異なります。通常、このモックを使用しない場合は削除するだけです。しかし、時々、パラメータ化されたテストに特定のケースがあり、それはこの異なる道をたどるか、あるいは早く失敗するべきです。それからあなたはこのテストを2つ以上の別々のものに分割することができますが、それはいつも見栄えがよくありません。おそらく3つの引数プロバイダを持つ3つのテストメソッドは、あなたがテストを読めなくすることができます。その場合JUnit 4では、この例外をどちらか一方で黙らせます。
@RunWith(MockitoJUnitRunner.Silent.class)
注釈またはルールアプローチを使用している場合
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.LENIENT);
または(同じ動作)
@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();
JUnit 5のテストではmockito-junit-jupiter
パッケージで提供されるアノテーションを使ってこの例外を黙らせることができます。
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class JUnit5MockitoTest {
}
when(dao.doSearch(dto)).thenReturn(inspectionsSummaryList);//got error in this line
verify(dao).doSearchInspections(dto);
ここのwhen
は、モックが何かをするように設定します。ただし、この行以降は、このモックを使用しないでください(verify
を除く)。 Mockitoはwhen
行はそれゆえ無意味であるとあなたに警告します。おそらくあなたは論理エラーを犯しましたか?
Silentは解決策ではありません。テストでモックを修正する必要があります。公式文書ここを参照してください。
不要なスタブは、テストの実行中に認識されなかったスタブ化されたメソッド呼び出しです(MockitoHintも参照)。次に例を示します。
//code under test:
...
String result = translator.translate("one")
...
//test:
...
when(translator.translate("one")).thenReturn("jeden"); // <- stubbing realized during code execution
when(translator.translate("two")).thenReturn("dwa"); // <- stubbing never realized
...
テスト実行中に、スタブ化されたメソッドの1つがテスト中のコードで実現されたことがないことに注意してください。厄介なスタブは、開発者の見落とし、コピー&ペーストのアーティファクト、あるいはテスト/コードを理解していない効果かもしれません。どちらにしても、開発者は不必要なテストコードになります。コードベースをクリーンで維持可能な状態に保つために、不要なコードを削除する必要があります。さもなければテストは読みにくくなり、それについて推論します。
未使用のスタブを検出することについてもっと知るためにはMockitoHintを見てください。
私にとっては@Rule
も@RunWith(MockitoJUnitRunner.Silent.class)
の提案もうまくいきませんでした。それは私たちがmockito-core 2.23.0にアップグレードしたレガシープロジェクトでした。
以下を使用してUnnecessaryStubbingException
を削除できます。
Mockito.lenient().when(mockedService.getUserById(any())).thenReturn(new User());
の代わりに:
when(mockedService.getUserById(any())).thenReturn(new User());
言うまでもなく、テストコードを見るべきですが、まず最初に、コンパイルしたものとテストを実行する必要がありました。
スタックトレースの一部を見ると、他の場所でdao.doSearch()
をスタブしているように見えます。同じメソッドのスタブを繰り返し作成するようなものです。
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at service.Test.testDoSearch(Test.Java:72)
Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class.
例えば、以下のテストクラスを考えてください。
@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
@Mock
Service1 svc1Mock1;
@Mock
Service2 svc2Mock2;
@InjectMock
TestClass class;
//Assume you have many dependencies and you want to set up all the stubs
//in one place assuming that all your tests need these stubs.
//I know that any initialization code for the test can/should be in a
//@Before method. Lets assume there is another method just to create
//your stubs.
public void setUpRequiredStubs() {
when(svc1Mock1.someMethod(any(), any())).thenReturn(something));
when(svc2Mock2.someOtherMethod(any())).thenReturn(somethingElse);
}
@Test
public void methodUnderTest_StateUnderTest_ExpectedBehavior() {
// You forget that you defined the stub for svcMock1.someMethod or
//thought you could redefine it. Well you cannot. That's going to be
//a problem and would throw your UnnecessaryStubbingException.
when(svc1Mock1.someMethod(any(),any())).thenReturn(anyThing);//ERROR!
setUpRequiredStubs();
}
}
私はむしろあなたのテストを必要に応じてスタブするようにリファクタリングすることを考えたいと思います。
あなたが代わりにこのスタイルを使っているならば:
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
それを置き換えます:
@Rule
public MockitoRule rule = MockitoJUnit.rule().silent();
大規模なプロジェクトの場合、これらの例外をそれぞれ修正することは困難です。同時に、Silent
を使用することはお勧めできません。私はそれらのリストを与えられたすべての不要なスタブを削除するスクリプトを書きました。
https://Gist.github.com/cueo/da1ca49e92679ac49f808c7ef594e75b
mvn
の出力をコピー&ペーストして、regexを使用してこれらの例外のリストを書き、残りをスクリプトに処理させるだけです。