program tip

예외 Junit 4.10 후 Mockito 확인

radiobox 2020. 11. 25. 07:49
반응형

예외 Junit 4.10 후 Mockito 확인


예상되는 예외가있는 메서드를 테스트하고 있습니다. 또한 예외가 발생한 후 일부 정리 코드가 (모의 객체에서) 호출되었는지 확인해야하지만 확인이 무시되는 것 같습니다. 다음은 코드입니다. ExpectedException Rule예상되는 예외를 확인하기 위해 Junit 을 사용하고 있습니다.

@Rule
public ExpectedException expectedEx = ExpectedException.none();

@Test
public void testExpectedException()
{
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   expectedEx.expect(MyException.class);
   expectedEx.expectMessage("My exception message.");
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

verify완전히 무시되는 것 같습니다 . 에 어떤 방법을 넣어도 verify내 테스트는 통과하고 있으며 이는 내가 원하는 것이 아닙니다.

왜 그런 일이 일어나는지 아십니까?


ExpectedExceptionJUnit @Rule을 통해 try-catch 블록에 전체 테스트 메서드래핑하여 작동합니다 . 코드에서 예외가 발생하면 가장 가까운 try / catch로 스택이 올라가고, ExpectedException 인스턴스 (예상하는 예외인지 확인)에 있습니다.

Java에서는 메서드에서 포착되지 않은 예외가 발생하면 제어가 나중에 해당 메서드의 명령문으로 반환되지 않습니다. 여기에도 동일한 규칙이 적용됩니다. 제어는 예외 후에 테스트의 문으로 반환되지 않습니다.

기술적으로는 최종 블록에 검증을 넣을 수 있지만 이는 나쁜 습관 인 경향이 있습니다 . 편집 : 테스트중인 시스템에서 예기치 않은 예외가 발생하거나 전혀 예외가 발생하지 않아 유용한 실패 메시지와 추적을 제공 할 수 있습니다. 그러나 그 실패로 인해 finally블록 에서 확인 또는 어설 션이 실패하면 Java는 예기치 않은 예외 또는 예기치 않은 성공에 대한 메시지가 아니라이를 표시합니다. 특히 오류의 근본 원인을 따르는 코드 줄에서 오류가 발생하여 위의 코드가 성공했음을 잘못 암시하기 때문에 디버깅이 어려울 수 있습니다.

예외 이후에 메서드별로 상태를 확인해야하는 경우 언제든지이 관용구로 되돌릴 수 있습니다.

@Test
public void testExpectedException()
{
  MockedObject mockObj = mock(MockedObj.class);
  MySubject subject = new MySubject(mockedObj);
  try {
    subject.someMethodThrowingException();
    fail("Expected MyException.");
  } catch (MyException expected) {
    assertEquals("My exception message.", expected.getMessage());
  }
  verify(mockObj).someCleanup(eq(...));
}

업데이트 : Java 8의 람다 표현식을 사용하면 기능 인터페이스 호출을 유용 할만큼 간결하게 try 블록에 래핑 할 수 있습니다 . 이 구문에 대한 지원이 많은 표준 테스트 라이브러리에 적용될 것이라고 생각합니다.

assertThrows(MyException.class,
    () -> systemUnderTest.throwingMethod());

catch-exception이있는 보다 우아한 솔루션

@Test
public void testExpectedException()
{
    MockedObject mockObj = mock(MockedObject.class);
    MySubject subject = new MySubject(mockObj);

    when(subject).someMethodThrowingException();

    then(caughtException())
            .isInstanceOf(MyException.class)
            .hasMessage("My exception message.");

    verify(mockObj).someCleanup(eq(...));
}

나는 이것을 아직 시도하지 않았지만 Jeff Bowman의 훌륭한 대답 외에도 try ... finally 구성과 함께 ExpectedException 규칙을 사용하여 finally 블록에 확인 문을 배치하도록 선택할 수 있습니다.


UT에서 Exception이 발생하면 그 아래의 모든 코드가 무시됩니다.

@Test(expected = Exception.class)
public void testExpectedException() {
   MockedObject mockObj = mock(MockedObj.class);
   MySubject subject = new MySubject(mockedObj);
   subject.doSomething(); // If this line results in an exception then all the code below this will be ignored.
   subject.someMethodThrowingException();
   verify(mockObj).
       someCleanup(eq(...));
}

이에 대응하고 모든 호출을 확인하기 위해 finally 와 함께 try사용할 수 있습니다 .

@Test(expected = Exception.class)
    public void testExpectedException() {
          MockedObject mockObj = mock(MockedObj.class);
          MySubject subject = new MySubject(mockedObj);
          try {
               subject.someMethodThrowingException(); 
          } finally {
             verify(mockObj).
             someCleanup(eq(...));
          }
} 

참고URL : https://stackoverflow.com/questions/13224288/mockito-verify-after-exception-junit-4-10

반응형