your programing

불필요한 스터 빙 예외를 해결하는 방법

lovepro 2020. 10. 13. 08:21
반응형

불필요한 스터 빙 예외를 해결하는 방법


내 코드는 다음과 같습니다.

@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 가지 경우가 있습니다. 첫째, 잘못된 방법을 조롱하고 있습니다 (오타를 만들었거나 다른 사람이 모의 방법을 더 이상 사용하지 않도록 테스트 된 코드를 변경했습니다). 둘째,이 메서드가 호출되기 전에 테스트가 실패합니다. 셋째, 논리가 코드의 어딘가에 잘못된 if / switch 분기에 속하므로 mocked 메서드가 호출되지 않습니다.

이것이 첫 번째 경우라면 항상 코드에서 사용되는 모의 메서드를 변경하고 싶습니다. 두 번째와 세 번째는 다릅니다. 일반적으로 사용하지 않는 경우이 mock을 삭제해야합니다. 그러나 때때로 매개 변수화 된 테스트에는이 다른 경로를 사용하거나 더 일찍 실패해야하는 특정 사례가 있습니다. 그런 다음이 테스트를 두 개 이상의 개별 테스트로 나눌 수 있지만 항상 좋은 것은 아닙니다. 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따라서 선이 무의미하다고 경고합니다 . 논리 오류를 범 하셨나요?


침묵은 해결책이 아닙니다. 테스트에서 모의를 수정해야합니다. 여기에서 공식 문서를 참조 하십시오 .

불필요한 스텁은 테스트 실행 중에 실현되지 않은 스텁 메서드 호출입니다 (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
 ...

스텁 메서드 중 하나는 테스트 실행 중에 테스트중인 코드에서 실현되지 않았습니다. 이탈 스터 빙은 개발자의 감독, 복사-붙여 넣기의 아티팩트 또는 테스트 / 코드를 이해하지 못하는 효과 일 수 있습니다. 어느 쪽이든 개발자는 불필요한 테스트 코드로 끝납니다. 코드베이스를 깨끗하고 유지 관리 할 수 ​​있도록 유지하려면 불필요한 코드를 제거해야합니다. 그렇지 않으면 테스트를 읽고 추론하기가 더 어렵습니다.

사용하지 않는 스터 빙 감지에 대한 자세한 내용은 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();

나는 Spy 개체에 메서드 UnnecessaryStubbingException를 사용하려고 할 때 가졌습니다 when. Mockito.lenient()예외를 음소거했지만 테스트 결과가 올바르지 않습니다.

Spy 개체의 경우 메서드를 직접 호출해야합니다.

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)
class ArithmTest {

    @Spy
    private Arithm arithm;

    @Test
    void testAddition() {

        int res = arithm.add(2, 5);

        // doReturn(7).when(arithm).add(2, 5);
        assertEquals(res, 7);
    }
}

In case of a large project, it's difficult to fix each of these exceptions. At the same time, using Silent is not advised. I have written a script to remove all the unnecessary stubbings given a list of them.

https://gist.github.com/cueo/da1ca49e92679ac49f808c7ef594e75b

We just need to copy-paste the mvn output and write the list of these exceptions using regex and let the script take care of the rest.


Well, In my case Mockito error was telling me to call the actual method after the when or whenever stub. Since we were not invoking the conditions that we just mocked, Mockito was reporting that as unnecessary stubs or code.

Here is what it was like when the error was coming :

@Test
fun `should return error when item list is empty for getStockAvailability`() {
    doAnswer(
        Answer<Void> { invocation ->
            val callback =
                invocation.arguments[1] as GetStockApiCallback<StockResultViewState.Idle, StockResultViewState.Error>
            callback.onApiCallError(stockResultViewStateError)
            null
        }
    ).whenever(stockViewModelTest)
        .getStockAvailability(listOf(), getStocksApiCallBack)
}

then I just called the actual method mentioned in when statement to mock the method.

changes done is as below stockViewModelTest.getStockAvailability(listOf(), getStocksApiCallBack)

@Test
fun `should return error when item list is empty for getStockAvailability`() {
    doAnswer(
        Answer<Void> { invocation ->
            val callback =
                invocation.arguments[1] as GetStockApiCallback<StockResultViewState.Idle, StockResultViewState.Error>
            callback.onApiCallError(stockResultViewStateError)
            null
        }
    ).whenever(stockViewModelTest)
        .getStockAvailability(listOf(), getStocksApiCallBack)
    //called the actual method here
    stockViewModelTest.getStockAvailability(listOf(), getStocksApiCallBack)
}

it's working now.


I faced this issue when upgrading to mockito-core:2.18.0 and powermock-module-junit4:2.0.0-beta.5

Above answers did helped me. Along with that, make sure you change

Old Code:

import org.mockito.runners.MockitoJUnitRunner;

New Code:

import org.mockito.junit.MockitoJUnitRunner;

참고URL : https://stackoverflow.com/questions/42947613/how-to-resolve-unneccessary-stubbing-exception

반응형