JUnit 테스트 주석으로 예외 메시지를 어떻게 확인합니까? 작성했습니다 . 테스트 메소드에서 확인 된

@Test주석이 있는 몇 가지 JUnit 테스트를 작성했습니다 . 테스트 메소드에서 확인 된 예외가 발생하고 예외와 함께 메시지를 표시하려는 경우 JUnit @Test주석 으로 처리 할 수있는 방법이 있습니까? AFAIK, JUnit 4.7은이 기능을 제공하지 않지만 이후 버전에서는이 기능을 제공합니까? .NET에서 메시지와 예외 클래스를 주장 할 수 있다는 것을 알고 있습니다. 자바 세계에서 비슷한 기능을 찾고 있습니다.

이것이 내가 원하는거야:

@Test (expected = RuntimeException.class, message = "Employee ID is null")
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() {}



답변

다음 @RuleExpectedException같이 주석을 사용할 수 있습니다 .

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

@Test
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() throws Exception {
    expectedEx.expect(RuntimeException.class);
    expectedEx.expectMessage("Employee ID is null");

    // do something that should throw the exception...
    System.out.println("=======Starting Exception process=======");
    throw new NullPointerException("Employee ID is null");
}

ExpectedException문서 의 예제 는 (현재) 잘못되었습니다-공용 생성자가 없으므로을 사용해야 ExpectedException.none()합니다.


답변

나는 @Rule대답을 좋아한다 . 그러나 어떤 이유로 규칙을 사용하지 않으려는 경우. 세 번째 옵션이 있습니다.

@Test (expected = RuntimeException.class)
public void myTestMethod()
{
   try
   {
      //Run exception throwing operation here
   }
   catch(RuntimeException re)
   {
      String message = "Employee ID is null";
      assertEquals(message, re.getMessage());
      throw re;
    }
    fail("Employee Id Null exception did not throw!");
  }


답변

사용해야 @Test(expected=SomeException.class)합니까? 예외의 실제 메시지를 주장해야 할 때 이것이 바로 우리의 일입니다.

@Test
public void myTestMethod()
{
  try
  {
    final Integer employeeId = null;
    new Employee(employeeId);
    fail("Should have thrown SomeException but did not!");
  }
  catch( final SomeException e )
  {
    final String msg = "Employee ID is null";
    assertEquals(msg, e.getMessage());
  }
}


답변

JUnit 4.13에서는 다음을 수행 할 수 있습니다.

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

...

@Test
void exceptionTesting() {
  IllegalArgumentException exception = assertThrows(
    IllegalArgumentException.class,
    () -> { throw new IllegalArgumentException("a message"); }
  );

  assertEquals("a message", exception.getMessage());
}

이것은 JUnit 5 에서도 작동 하지만 가져 오기가 다릅니다.

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

...


답변

실제로 가장 좋은 사용법은 try / catch입니다. 왜? 예외가 예상되는 장소를 제어 할 수 있기 때문입니다.

이 예제를 고려하십시오.

@Test (expected = RuntimeException.class)
public void someTest() {
   // test preparation
   // actual test
}

언젠가 코드가 수정되고 테스트 준비에서 RuntimeException이 발생하면 어떻게됩니까? 이 경우 실제 테스트는 테스트되지 않으며 예외가 발생하지 않더라도 테스트는 통과합니다.

따라서 주석에 의존하는 것보다 try / catch를 사용하는 것이 훨씬 좋습니다.


답변

Raystorm은 좋은 대답을했습니다. 나도 규칙을 좋아하지 않습니다. 나는 가독성과 유용성을 돕기 위해 다음과 같은 유틸리티 클래스를 만드는 것을 제외하고는 비슷한 것을 수행한다. 이것은 처음에는 주석의 큰 장점 중 하나입니다.

이 유틸리티 클래스를 추가하십시오.

import org.junit.Assert;

public abstract class ExpectedRuntimeExceptionAsserter {

    private String expectedExceptionMessage;

    public ExpectedRuntimeExceptionAsserter(String expectedExceptionMessage) {
        this.expectedExceptionMessage = expectedExceptionMessage;
    }

    public final void run(){
        try{
            expectException();
            Assert.fail(String.format("Expected a RuntimeException '%s'", expectedExceptionMessage));
        } catch (RuntimeException e){
            Assert.assertEquals("RuntimeException caught, but unexpected message", expectedExceptionMessage, e.getMessage());
        }
    }

    protected abstract void expectException();

}

그런 다음 단위 테스트를 위해 필요한 것은 다음 코드입니다.

@Test
public void verifyAnonymousUserCantAccessPrivilegedResourceTest(){
    new ExpectedRuntimeExceptionAsserter("anonymous user can't access privileged resource"){
        @Override
        protected void expectException() {
            throw new RuntimeException("anonymous user can't access privileged resource");
        }
    }.run(); //passes test; expected exception is caught, and this @Test returns normally as "Passed"
}


답변

@Rule을 사용하는 경우 예외 세트는 Test 클래스의 모든 테스트 메소드에 적용됩니다.