programing

JUnit 테스트에서 catch 시도

shortcode 2021. 1. 19. 07:33
반응형

JUnit 테스트에서 catch 시도


이미 오랫동안 존재하는 애플리케이션에 대한 단위 테스트를 작성하고 있습니다. 테스트해야하는 방법 중 일부는 다음과 같이 빌드됩니다.

public void someMethod() throws Exception { 
   //do something 
}

이러한 메서드를 테스트하려면 단위 테스트에서 다음과 같이 작성해야합니다.

@Test
public void someTest() {
   try {
      someMethod();
   }
   catch (Exception e) {
      e.printStackTrace();
   }
}

이렇게하는 것이 좋은 습관입니까? 아니면 이러한 방법을 테스트하는 다른 방법이 있습니까?

인터넷에서 몇 가지 조사를했고 @Rule주석 및 으로 몇 가지 솔루션을 찾았 @Test(expected=Exception.class)지만 작동하지 않습니다 (Eclipse someMethod()는 테스트 에서 줄을 계속 잘못 표시 함). 나는 전체 단위 테스트 이야기에 익숙하지 않기 때문에 이것이 좋은 해결책인지 모르겠습니다.

이것에 대해 많이 아는 사람이 나를 도울 수 있다면 정말 감사 할 것입니다.


이후 ExceptionA는 예외를 체크, 하나 당신 :

  • try...catch명령문 에서 예외를 포착해야합니다 .
  • 메서드 자체에서 throw 될 예외를 선언합니다.

당신이 가지고있는 것은 잘 작동하지만, 개인적으로 선호하는 것은 예외가 던져 질 것이라고 선언하는 것입니다. 이렇게하면 테스트 실행 중에 예상치 못한 예외가 발생하면 테스트가 실패 합니다.

@Test
public void someTest() throws Exception {
    // dodgy code here
}

특정 예외가 발생했는지 확인해야하는 경우 주석에 직접 @Rule값을 사용 하거나 추가 할 수 @Test있습니다.

@Test(expected = FileNotFoundException.class)
public void someTest() throws Exception {
    // dodgy code here
}

JUnit 5에서는 Assertions.expectThrows동일한 작업을 수행하는 데 활용할 수 있습니다 . 편집 당시에는 아직 GA가 아니기 때문에 전반적으로 익숙하지 않지만 ExecutableJUnit 5에서 오는 것을 받아들이는 것 같습니다.

@Test
public void someTest() {
    assertThrows(FileNotFoundException.class, () ->
         { dodgyService.breakableMethod() };
}

@Test
public void someTest() {
   try {
     someMethod();
   }
   catch (Exception e) {
     Assert.fail("Exception " + e);
   }
}

예외가 발생하지 않아야하는 경우 수행 할 수있는 작업입니다. 대안은 다음과 같이 서명에서 예외를 throw하는 것입니다.

@Test
public void someTest() throws Exception {
     someMethod();
}

차이점은 어떤 경우에는 어설 션 예외로 인해 테스트가 실패하고 다른 경우에는 테스트가 충돌하여 실패한다는 것입니다. (코드 어딘가에서 NPE를 얻고 그 때문에 테스트가 수행됩니다)

이렇게해야하는 이유는 Exception이 확인 된 예외이기 때문입니다. 확인 된 예외와 확인되지 않은 예외를 참조하십시오.

@Test (expected = Exception.class)는 예외가 발생하는지 테스트하려는 테스트 용입니다.

@Test(expected=ArrayIndexOutOfBounds.class)
public void testIndex() {
   int[] array = new int[0];
   int var = array[0]; //exception will be thrown here, but test will be green, because we expect this exception

}

테스트 코드에서 애플리케이션의 예외를 포착하지 마십시오. 대신 위쪽으로 던지도록 선언하십시오.

JUnit이 TestRunner예외가 발생하면 자동으로이를 error테스트 케이스 로 기록하기 때문 입니다.

testcase메서드가 throw되어야한다고 예상하는 경우에만 예외를 Exception사용 @Test(expected=Exception.class)하거나 포착 해야합니다 .

다른 경우에는 위쪽으로 던져서

public void someTest() throws Exception {

테스트 메서드 서명에 예외를 추가 할 수 있습니다. 그런 다음 예외 발생 여부를 테스트하는 경우 @Test(expected=Exception.class). 예외가 발생하지 않아야하는 테스트 케이스에서는 테스트가 성공적으로 통과됩니다.

@Test
public void testCaseWhereExceptionWontBeThrown() throws Exception {
    someMethod(); //Test pass
}

@Test(expected = Exception.class)
public void testCaseWhereExceptionWillBeThrown() throws Exception {
    someMethod(); //Test pass
}

Junit 테스터에서 예외를 처리하는 방법에는 두 가지 주요 규칙이 있습니다.

  1. 예외가 테스트 된 코드에서 발생한 경우 :

    • If it was expected, declare it in the expected attribute of the Test annotation. Or, if further checks should be done on the exception object itself, catch it and ignore it. (In this case, there must be also a call to Assert.fail at the end of the try block, to indicate that the expected exception was not produced).
    • If it was not expected, catch it and execute Assert.fail. (A previous call to Exception.printStackTrace is also useful).
  2. If the exception was not originated into the tested code or it is not interesting to the test (for example, most of the IOExceptions are produced at network level, before the test could even be completed), rethrow it at the throws clause.

Why you should expect an exception in the tester? Remind: You should code one test method for every possible result on the tested code (in order to achieve a high code coverage): In your case, one method that must return successfully, and at least another one that must produce an Exception.


Three points about JUnit:

  • Tests should be precise, they should pass or fail unambiguously based solely on how the test inputs are set up.

  • Tests should have failures reported back into the framework.

  • Tests should not rely on having their output read.

Your example fails on all three counts. If an exception gets thrown or not, the test still passes. If an exception is thrown JUnit never finds out about it and can't include it in the test results. The only way to know something went wrong is to read what the test writes to stdout, which makes errors too easy to ignore. This is not a useful way to write tests.

JUnit was designed to make doing the right thing easy and to give developers useful feedback. If an exception gets thrown from a test method, it gets caught by the framework. If the test was annotated with an exception indicating that exception is expected, then the framework marks the test as passing. Otherwise the framework fails the test and records the stacktrace for reporting. The framework reports what assertions fail and what unexpected exceptions occurred so that everybody knows if the tests worked or not.

If you expect a test to succeed without throwing an exception, then if anything in the test can throw a checked exception, add throws Exception to the test method signature. Adding the throws to the signature doesn't say the method has to throw anything, it just lets any exceptions that happen to occur get thrown so that the test framework can catch them.

The only instance where you would actually catch the exception in the test is where you want to test assertions about the exception; for instance, you could test that the message on the exception is what you expect, or if the exception has a cause set on it. In that case you would add Assert.fail() at the end of the try-block so that not having an exception thrown will cause the test to fail.

When you write a test at first, make it fail. That way you prove to yourself that you know what the test is doing, and you confirm that, when there is a failure, you will be made aware of it.


What kind of exception is it? Is it

  1. an exception from doing something like using streams that won't happen in your unit test or
  2. an exception that can happen because of some kind of bad input?

If it's 1. I would just put it at the method signature level because a try-catch is serving no real purpose other than ceremony.

@Test
public void testFoo() throws Exception {
    // ...
}

If it's 2. it becomes a little more complicated. You need to ask yourself what should be happening if the Exception is thrown. Should the test fail? Is it expected? Is it irrelevant? Examples below of how to handle all of these. BEWARE: I only used Exception because you did. I hope it really isn't though because if it's possible for some other exception to be thrown other than the expected then these will be very wonky. If possible don't use Exception, use something more specific (in the junit and code).

// The below code assumes you've imported the org.junit.Assert class.

@Test
public void thisShouldFailIfExceptionCaught() {
    //Given...
    try {
        // When...
    } catch (Exception e) {
        Assert.fail();
    }
    // Then...
}

@Test
public void thisShouldPassOnlyIfTheExceptionIsCaught() {
    //Given...
    try {
        // When...
        Assert.fail();
    } catch (Exception expected) {}
    // No "then" needed, the fact that it didn't fail is enough.
}

@Test
public void irrelevantExceptionThatCouldBeThrown() {
    //Given...
    try {
        // When...
    } catch (Exception e) {}
    // Then...
}

ReferenceURL : https://stackoverflow.com/questions/31423643/try-catch-in-a-junit-test

반응형