IT

JUnit 5 : 예외를 선언하는 방법은 무엇입니까?

lottoking 2020. 6. 12. 08:32
반응형

JUnit 5 : 예외를 선언하는 방법은 무엇입니까?


JUnit 5에서 메소드가 예외를 처리한다고 주장하는 더 좋은 방법이 있습니까?

현재 테스트에서 예외가 발생하는지 확인하기 위해 @Rule을 사용해야하지만 테스트에서 여러 메소드가 예외를 throw 할 것으로 예상되는 경우에는 작동하지 않습니다.


를 사용 assertThrows()하면 동일한 테스트 내에서 여러 예외를 테스트 할 수 있습니다. Java 8에서 람다를 지원하므로 JUnit에서 예외를 테스트하는 정식 방법입니다.

의 JUnit 문서 :

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

@Test
void exceptionTesting() {
    MyException thrown =
        assertThrows(MyException.class,
           () -> myObject.doThing(),
           "Expected doThing() to throw, but it didn't");

    assertTrue(thrown.getMessage().contains("Stuff"));
}

Java 8 및 JUnit 5 (Jupiter)에서는 다음과 같이 예외를 주장 할 수 있습니다. 사용org.junit.jupiter.api.Assertions.assertThrows

공개 정적 <T 확장 가능 Throwable> T assertThrows (Class <T> expectType, 실행 가능 실행 파일)

제공된 실행 파일을 실행하면 expectType의 예외가 발생하고 예외를 반환합니다.

예외가 발생하지 않거나 다른 유형의 예외가 발생하면이 메소드는 실패합니다.

예외 인스턴스에서 추가 점검을 수행하지 않으려면 리턴 값을 무시하십시오.

@Test
public void itShouldThrowNullPointerExceptionWhenBlahBlah() {
    assertThrows(NullPointerException.class,
            ()->{
            //do whatever you want to do here
            //ex : objectName.thisMethodShoulThrowNullPointerExceptionForNullParameter(null);
            });
}

이 방법은의 기능 인터페이스 Executable사용합니다 org.junit.jupiter.api.

참조 :


그들은 JUnit 5에서 그것을 변경했으며 (예상 : InvalidArgumentException, actual : invoked 메소드) 코드는 다음과 같습니다.

@Test
public void wrongInput() {
    Throwable exception = assertThrows(InvalidArgumentException.class,
            ()->{objectName.yourMethod("WRONG");} );
}

이제 Junit5는 예외를 주장하는 방법을 제공합니다

일반 예외와 사용자 정의 예외를 모두 테스트 할 수 있습니다

일반적인 예외 시나리오 :

ExpectGeneralException.java

public void validateParameters(Integer param ) {
    if (param == null) {
        throw new NullPointerException("Null parameters are not allowed");
    }
}

ExpectGeneralExceptionTest.java

@Test
@DisplayName("Test assert NullPointerException")
void testGeneralException(TestInfo testInfo) {
    final ExpectGeneralException generalEx = new ExpectGeneralException();

     NullPointerException exception = assertThrows(NullPointerException.class, () -> {
            generalEx.validateParameters(null);
        });
    assertEquals("Null parameters are not allowed", exception.getMessage());
}

여기에서 CustomException을 테스트 할 샘플을 찾을 수 있습니다. assert exception code sample

ExpectCustomException.java

public String constructErrorMessage(String... args) throws InvalidParameterCountException {
    if(args.length!=3) {
        throw new InvalidParameterCountException("Invalid parametercount: expected=3, passed="+args.length);
    }else {
        String message = "";
        for(String arg: args) {
            message += arg;
        }
        return message;
    }
}

ExpectCustomExceptionTest.java

@Test
@DisplayName("Test assert exception")
void testCustomException(TestInfo testInfo) {
    final ExpectCustomException expectEx = new ExpectCustomException();

     InvalidParameterCountException exception = assertThrows(InvalidParameterCountException.class, () -> {
            expectEx.constructErrorMessage("sample ","error");
        });
    assertEquals("Invalid parametercount: expected=3, passed=2", exception.getMessage());
}

사용할 수 있습니다 assertThrows(). 내 예는 http://junit.org/junit5/docs/current/user-guide/ 문서에서 가져 왔습니다.

import org.junit.jupiter.api.Test;

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

....

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

나는 이것이 더 간단한 예라고 생각한다.

List<String> emptyList = new ArrayList<>();
Optional<String> opt2 = emptyList.stream().findFirst();
assertThrows(NoSuchElementException.class, () -> opt2.get());

get()비어있는 ArrayList것을 포함하는 옵션을 호출 하면가 발생합니다 NoSuchElementException. assertThrows예상되는 예외를 선언하고 람다 공급자를 제공합니다 (인수를 취하지 않고 값을 반환 함).

내가 잘 설명 한 그의 답변에 대한 @prime에게 감사드립니다.


Actually I think there is a error in the documentation for this particular example. The method that is intended is expectThrows

public static void assertThrows(
public static <T extends Throwable> T expectThrows(

Here is an easy way.

@Test
void exceptionTest() {

   try{
        model.someMethod("invalidInput");
        fail("Exception Expected!");
   }
   catch(SpecificException e){

        assertTrue(true);
   }
   catch(Exception e){
        fail("wrong exception thrown");
   }

}

It only succeeds when the Exception you expect is thrown.


There are 3 ways to assert a certain exception in Junit. Let's write the unit test cases for it.

1. try-catch idiom This idiom is one of the most popular ones because it was used already in JUnit 3. This approach is a common pattern. The test will fail when no exception is thrown and the exception itself is verified in a catch clause.

@Test
public void convertIntoUpperCase_withInvalidInput_tryCatchIdiom() {
    try {
        exceptionHandling.convertIntoUpperCase("");
        fail("It should throw IllegalArgumentException");
    } catch (IllegalArgumentException e) {
        Assertions.assertThat(e)
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("Empty value is passed.");
    }
}

2. @Test expected annotation In this approach, we specify the expected exception in @Test as below @Test(expected = IllegalArgumentException.class)

When the exception wasn’t thrown you will get the following message: java.lang.AssertionError: Expected exception: java.lang.IllegalArgumentException

With this approach, you need to be careful though. Sometimes it is tempting to expect general Exception, RuntimeException or even a Throwable. And this is considered as a bad practice because your code may throw an exception in other places than you actually expected and your test will still pass!

One of the drawback of this approach is you can’t assert for the exception message.

@Test(expected = IllegalArgumentException.class)
public void convertIntoUpperCase_withInvalidInput_testExpected() {
    exceptionHandling.convertIntoUpperCase("");
}

3. Junit @Rule The same example can be created using ExceptedException rule. The rule must be a public field marked with @Rule annotation.

    @Test
    public void convertIntoUpperCase_withInvalidInput_ExpectedExceptionRule() {
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("Empty value is passed.");
        exceptionHandling.convertIntoUpperCase("");
    }

I find the above code more readable hence I prefer to use this approach.

When the exception isn’t thrown you will get the following message: java.lang.AssertionError: Expected test to throw (an instance of java.lang.IllegalArgumentException and exception with the message “Empty value is passed.”). Pretty nice.

But not all exceptions I check with the above approach. Sometimes I need to check only the type of the exception thrown and then I use @Test annotation.

참고URL : https://stackoverflow.com/questions/40268446/junit-5-how-to-assert-an-exception-is-thrown

반응형