etc./StackOverFlow

JUnit 4 테스트에서 특정 예외가 발생했다고 어떻게 주장합니까?

청렴결백한 만능 재주꾼 2021. 11. 29. 22:34
반응형

질문자 :SCdF


JUnit4를 관용적으로 사용하여 일부 코드에서 예외가 발생하는지 테스트하려면 어떻게 해야 합니까?

확실히 다음과 같이 할 수 있습니다.

 @Test public void testFooThrowsIndexOutOfBoundsException() { boolean thrown = false; try { foo.doStuff(); } catch (IndexOutOfBoundsException e) { thrown = true; } assertTrue(thrown); }

나는 훨씬 덜 미봉책 훨씬 더 - 더 - 정신 상황의 이러한 종류에 대한의 JUnit입니다 주석 또는 Assert.xyz 또는 뭔가가 있다는 것을 기억합니다.



JUnit 버전과 사용하는 어설션 라이브러리에 따라 다릅니다.

JUnit <= 4.12 에 대한 원래 답변은 다음과 같습니다.

 @Test(expected = IndexOutOfBoundsException.class) public void testIndexOutOfBoundsException() { ArrayList emptyList = new ArrayList(); Object o = emptyList.get(0); }

https://stackoverflow.com/a/31826781/2986984 답변에는 JUnit <= 4.12에 대한 더 많은 옵션이 있습니다.

참조 :


skaffman

편집: 이제 JUnit 5 및 JUnit 4.13이 릴리스되었으므로 가장 좋은 옵션은 Assertions.assertThrows() (JUnit 5의 경우) 및 Assert.assertThrows() (JUnit 4.13+의 경우)를 사용하는 것입니다. 자세한 내용은 내 다른 답변 을 참조하십시오.

JUnit 5로 마이그레이션하지 않았지만 JUnit 4.7을 사용할 수 있는 경우 ExpectedException 규칙을 사용할 수 있습니다.

 public class FooTest { @Rule public final ExpectedException exception = ExpectedException.none(); @Test public void doStuffThrowsIndexOutOfBoundsException() { Foo foo = new Foo(); exception.expect(IndexOutOfBoundsException.class); foo.doStuff(); } }

foo.doStuff() IndexOutOfBoundsException 이 발생하면 테스트가 실패하므로 @Test(expected=IndexOutOfBoundsException.class) 보다 훨씬 낫습니다.

자세한 내용은 이 문서 를 참조하십시오.


NamshubWriter

테스트 의 특정 코드 줄이 아니라 메서드 가 해당 예외를 throw했다고 주장하기 때문에 예상되는 예외를 사용하는 데 주의하십시오.

나는 매개변수 유효성 검사를 테스트하기 위해 이것을 사용하는 경향이 있습니다. 왜냐하면 그러한 방법은 일반적으로 매우 간단하지만 더 복잡한 테스트는 다음과 함께 제공하는 것이 더 나을 수 있기 때문입니다.

 try { methodThatShouldThrow(); fail( "My method didn't throw when I expected it to" ); } catch (MyException expectedException) { }

판단을 적용합니다.


daveb

이전에 답변한 것처럼 JUnit에서 예외를 처리하는 방법에는 여러 가지가 있습니다. 그러나 Java 8에는 Lambda 표현식을 사용하는 또 다른 방법이 있습니다. Lambda 표현식을 사용하면 다음과 같은 구문을 얻을 수 있습니다.

 @Test public void verifiesTypeAndMessage() { assertThrown(new DummyService()::someMethod) .isInstanceOf(RuntimeException.class) .hasMessage("Runtime exception occurred") .hasMessageStartingWith("Runtime") .hasMessageEndingWith("occurred") .hasMessageContaining("exception") .hasNoCause(); }

assertThrown은 람다 식, 메서드 참조 또는 생성자 참조로 인스턴스를 생성할 수 있는 기능 인터페이스를 허용합니다. 해당 인터페이스를 수락하는 assertThrown은 예외를 예상하고 처리할 준비가 됩니다.

이것은 비교적 간단하면서도 강력한 기술입니다.

이 기술을 설명하는 이 블로그 게시물을 살펴보십시오. http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

소스 코드는 https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8 에서 찾을 수 있습니다.

공개: 저는 블로그와 프로젝트의 저자입니다.


Rafal Borowiec

Junit에는 예외를 테스트하는 네 가지 방법이 있습니다.

Junit5.x

  • assertThrows 경우 다음과 같이 assertThrows를 사용할 수 있습니다.

     @Test public void testFooThrowsIndexOutOfBoundsException() { Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff()); assertEquals("expected messages", exception.getMessage()); }

Junit4.x

  • junit4.x의 경우 테스트 주석의 선택적 '예상' 속성을 사용합니다.

     @Test(expected = IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() { foo.doStuff(); }
  • junit4.x의 경우 ExpectedException 규칙을 사용하십시오.

     public class XxxTest { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testFooThrowsIndexOutOfBoundsException() { thrown.expect(IndexOutOfBoundsException.class) //you can test the exception message like thrown.expectMessage("expected messages"); foo.doStuff(); } }
  • junit 3 프레임워크에서 널리 사용되는 고전적인 try/catch 방식을 사용할 수도 있습니다.

     @Test public void testFooThrowsIndexOutOfBoundsException() { try { foo.doStuff(); fail("expected exception was not occured."); } catch(IndexOutOfBoundsException e) { //if execution reaches here, //it indicates this exception was occured. //so we need not handle it. } }
  • 그래서

    • junit 5가 마음에 든다면 첫 번째 것도 좋아해야 합니다.
    • 두 번째 방법은 예외 유형만 테스트하려는 경우에 사용됩니다.
    • 테스트 예외 메시지를 추가로 원할 때 처음과 마지막 두 개를 사용합니다.
    • junit 3을 사용하는 경우 4번째 것이 선호됩니다.
  • 자세한 내용은 이 문서junit5 사용자 가이드 를 참조하세요.


walsh

헐 박사

  • post-JDK8: AssertJ 또는 사용자 지정 람다를 사용하여 예외적인 동작을 주장합니다.

  • pre-JDK8 : 오래된 좋은 try - catch 블록을 추천합니다. ( catch 블록 fail() 어설션을 추가하는 것을 잊지 마세요 )

Junit 4 또는 JUnit 5에 관계없이.

긴 이야기

자신에게 쓸 수있는 그것을 할 자신이 try - catch 블록 또는 JUnit을 도구 (사용 @Test(expected = ...) 또는 @Rule ExpectedException 의 JUnit 규칙 기능).

그러나 이러한 방법은 그다지 우아하지 않으며 다른 도구와 가독성이 좋지 않습니다. 또한 JUnit 도구에는 몇 가지 함정이 있습니다.

  1. try - catch 블록 테스트된 동작 주위에 블록을 작성하고 catch 블록에 어설션을 작성해야 합니다. 괜찮을 수 있지만 많은 사람들은 이 스타일이 테스트의 읽기 흐름을 방해한다는 것을 알게 됩니다. try 블록 끝에 Assert.fail 을 작성해야 합니다. 그렇지 않으면 테스트에서 주장의 한 쪽이 누락될 수 있습니다. PMD , findbugs 또는 Sonar 가 이러한 문제를 찾아낼 것입니다.

  2. @Test(expected = ...) 기능은 더 적은 코드를 작성할 수 있고 이 테스트를 작성하면 코딩 오류가 덜 발생하기 때문에 흥미롭습니다. 그러나 이 접근 방식은 일부 영역에서 부족합니다.

    • 테스트에서 원인이나 메시지와 같은 예외에 대한 추가 사항을 확인해야 하는 경우(좋은 예외 메시지는 정말 중요하며 정확한 예외 유형을 갖는 것만으로는 충분하지 않을 수 있습니다).
    • 또한 테스트된 코드가 어떻게 작성되었는지에 따라 테스트 코드의 잘못된 부분이 예외를 throw하여 위양성 테스트로 이어질 수 있으며 PMD , findbugs 또는 Sonar가 확실하지 않습니다. 그러한 코드에 대한 힌트를 줄 것입니다.

       @Test(expected = WantedException.class) public void call2_should_throw_a_WantedException__not_call1() { // init tested tested.call1(); // may throw a WantedException // call to be actually tested tested.call2(); // the call that is supposed to raise an exception }
  3. ExpectedException 규칙도 이전 주의 사항을 수정하려는 시도이지만 예상 스타일을 사용하기 때문에 사용하기 약간 어색한 느낌이 들며 EasyMock 사용자는 이 스타일을 잘 알고 있습니다. 어떤 사람들에게는 편리할 수도 있지만 BDD( 행동 주도 개발 ) 또는 AAA(Arrange Act Assert ) 원칙을 따르는 경우 ExpectedException 규칙은 이러한 작성 스타일에 맞지 않습니다. @Test 기대하는 위치에 따라 @Test 방식과 동일한 문제가 발생할 수 있습니다.

     @Rule ExpectedException thrown = ExpectedException.none() @Test public void call2_should_throw_a_WantedException__not_call1() { // expectations thrown.expect(WantedException.class); thrown.expectMessage("boom"); // init tested tested.call1(); // may throw a WantedException // call to be actually tested tested.call2(); // the call that is supposed to raise an exception }

    예상되는 예외가 테스트 문 앞에 놓이더라도 테스트가 BDD 또는 AAA를 따르는 경우 읽기 흐름이 중단됩니다.

    ExpectedException 작성자의 JUnit에 대한 이 주석 문제를 참조하십시오. JUnit 4.13-beta-2는 심지어 이 메커니즘을 더 이상 사용하지 않습니다.

    풀 리퀘스트 #1519 : ExpectedException 지원 중단

    Assert.assertThrows 메서드는 예외를 확인하는 더 좋은 방법을 제공합니다. 또한, 규칙의 순서가 중요하기 때문에 TestWatcher와 같은 다른 규칙과 함께 사용할 때 ExpectedException을 사용하면 오류가 발생하기 쉽습니다.

따라서 위의 이러한 옵션에는 모든 주의 사항이 있으며 분명히 코더 오류에 영향을 받지 않습니다.

  1. 유망해 보이는 이 답변을 만든 후 알게 된 프로젝트가 있습니다. 그것은 catch-exception 입니다.

    프로젝트 설명에서 알 수 있듯이 코더는 예외를 포착하는 유창한 코드 줄을 작성하고 후자의 주장에 대해 이 예외를 제공할 수 있습니다. 그리고 Hamcrest 또는 AssertJ 와 같은 모든 주장 라이브러리를 사용할 수 있습니다.

    홈페이지에서 가져온 빠른 예:

     // given: an empty list List myList = new ArrayList(); // when: we try to get the first element of the list when(myList).get(1); // then: we expect an IndexOutOfBoundsException then(caughtException()) .isInstanceOf(IndexOutOfBoundsException.class) .hasMessage("Index: 1, Size: 0") .hasNoCause();

    당신이 코드는 정말 간단하다 볼 수 있듯이, 특정 라인에서 예외를 catch는 then API는 (사용하는 것과 비슷 AssertJ API를 사용하는 별칭입니다 assertThat(ex).hasNoCause()... ). 어느 시점에서 프로젝트는 AssertJ 의 조상 FEST-Assert 에 의존했습니다 . 편집: 프로젝트가 Java 8 Lambdas 지원을 양조하는 것 같습니다.

    현재 이 라이브러리에는 두 가지 단점이 있습니다.

    • 이 글을 쓰는 시점에서 이 라이브러리는 Mockito 1.x를 기반으로 하고 있다는 점은 주목할 만합니다. 이 라이브러리는 장면 뒤에서 테스트된 객체의 모의를 생성하기 때문입니다. Mockito가 아직 업데이트되지 않았기 때문에 이 라이브러리는 final 클래스나 final 메소드와 함께 작동할 수 없습니다 . 그리고 그것이 현재 버전의 Mockito 2를 기반으로 하였다 하더라도, 이것은 글로벌 모의 제작자( inline-mock-maker )를 선언해야 합니다. 만드는 사람.

    • 또 다른 테스트 종속성이 필요합니다.

    라이브러리가 람다를 지원하면 이러한 문제가 적용되지 않습니다. 그러나 기능은 AssertJ 도구 집합에 의해 복제됩니다.

    catch-exception 도구를 사용하고 싶지 않다면 모든 것을 고려하여 적어도 JDK7까지는 try - catch 그리고 JDK 8 사용자의 경우 AssertJ를 사용하는 것을 선호할 수 있습니다.

  2. JDK8을 사용하여 람다가 테스트 장면에 들어가고 예외적인 동작을 주장하는 흥미로운 방법으로 입증되었습니다. AssertJ는 예외적인 동작을 주장할 수 있는 유창한 API를 제공하도록 업데이트되었습니다.

    AssertJ를 사용한 샘플 테스트:

     @Test public void test_exception_approach_1() { ... assertThatExceptionOfType(IOException.class) .isThrownBy(() -> someBadIOOperation()) .withMessage("boom!"); } @Test public void test_exception_approach_2() { ... assertThatThrownBy(() -> someBadIOOperation()) .isInstanceOf(Exception.class) .hasMessageContaining("boom"); } @Test public void test_exception_approach_3() { ... // when Throwable thrown = catchThrowable(() -> someBadIOOperation()); // then assertThat(thrown).isInstanceOf(Exception.class) .hasMessageContaining("boom"); }
  3. JUnit 5의 거의 완전한 재작성으로 어설션이 약간 개선 되었으며 적절한 예외를 어설션하는 즉시 사용 가능한 방법으로 흥미로울 수 있습니다. 그러나 실제로 assertion API는 여전히 약간 열악하며 assertThrows 외부에는 아무 것도 없습니다.

     @Test @DisplayName("throws EmptyStackException when peeked") void throwsExceptionWhenPeeked() { Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek()); Assertions.assertEquals("...", t.getMessage()); }

    assertEquals 는 여전히 void 반환하고 있으므로 AssertJ와 같은 연결 어설션을 허용하지 않습니다.

    Matcher 또는 Assert 와 이름 충돌을 기억한다면 Assertions 와 동일한 충돌을 만날 준비를 하십시오.

오늘(2017-03-03) AssertJ 의 사용 용이성, 검색 가능한 API, 빠른 개발 속도 및 사실상 테스트 종속성이 테스트 프레임워크(JUnit 여부), 이전 JDK는 투박하다고 느껴지더라도 try - catch

이 답변은 동일한 가시성이 없는 다른 질문 에서 복사한 것입니다. 저는 동일한 작성자입니다.


Brice

이제 JUnit 5 및 JUnit 4.13이 릴리스되었으므로 가장 좋은 옵션은 Assertions.assertThrows() (JUnit 5의 경우) 및 Assert.assertThrows() (JUnit 4.13의 경우)를 사용하는 것입니다. JUnit 5 사용자 가이드를 참조하십시오.

다음은 예외가 발생했는지 확인하고 Truth 를 사용하여 예외 메시지에 대한 어설션을 만드는 예입니다.

 public class FooTest { @Test public void doStuffThrowsIndexOutOfBoundsException() { Foo foo = new Foo(); IndexOutOfBoundsException e = assertThrows( IndexOutOfBoundsException.class, foo::doStuff); assertThat(e).hasMessageThat().contains("woops!"); } }

다른 답변의 접근 방식에 비해 장점은 다음과 같습니다.

  1. JUnit에 내장
  2. 람다의 코드에서 예외가 발생하지 않으면 유용한 예외 메시지가 표시되고, 다른 예외가 발생하면 스택 추적이 표시됩니다.
  3. 간결한
  4. 테스트가 Arrange-Act-Assert를 따르도록 허용합니다.
  5. 예외를 던질 것으로 예상되는 코드를 정확하게 나타낼 수 있습니다.
  6. throws 절에 예상되는 예외를 나열할 필요가 없습니다.
  7. 선택한 어설션 프레임워크를 사용하여 catch된 예외에 대한 어설션을 만들 수 있습니다.

NamshubWriter

이것은 어떻습니까? 매우 일반적인 예외를 잡아서 catch 블록에서 벗어나도록 한 다음 예외의 클래스가 예상한 것과 같은지 확인하십시오. 이 주장은) 예외가 잘못된 유형이고(예: 대신 Null 포인터가 있는 경우) b) 예외가 발생하지 않은 경우 실패합니다.

 public void testFooThrowsIndexOutOfBoundsException() { Throwable e = null; try { foo.doStuff(); } catch (Throwable ex) { e = ex; } assertTrue(e instanceof IndexOutOfBoundsException); }

Johan

JUnit과 함께 사용할 수 있는 AssertJ 어설션 사용:

 import static org.assertj.core.api.Assertions.*; @Test public void testFooThrowsIndexOutOfBoundsException() { Foo foo = new Foo(); assertThatThrownBy(() -> foo.doStuff()) .isInstanceOf(IndexOutOfBoundsException.class); }

@Test(expected=IndexOutOfBoundsException.class) 보다 낫습니다. 테스트의 예상 라인이 예외를 던졌음을 보장하고 메시지와 같은 예외에 대한 자세한 내용을 더 쉽게 확인할 수 있기 때문입니다.

 assertThatThrownBy(() -> { throw new Exception("boom!"); }) .isInstanceOf(Exception.class) .hasMessageContaining("boom");

Maven/Gradle 지침은 여기에 있습니다.


weston

BDD 스타일 솔루션: JUnit 4 + 예외 캐치 + AssertJ

 import static com.googlecode.catchexception.apis.BDDCatchException.*; @Test public void testFooThrowsIndexOutOfBoundsException() { when(() -> foo.doStuff()); then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class); }

종속성

 eu.codearte.catch-exception:catch-exception:2.0

MariuszS

업데이트 : JUnit5이 테스트 예외에 대한 개선이 assertThrows .

다음 예제는 Junit 5 사용자 가이드 에서 가져온 것입니다.

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

JUnit 4를 사용한 원래 답변.

예외가 발생했는지 테스트하는 방법에는 여러 가지가 있습니다. 나는 또한 JUnit으로 훌륭한 단위 테스트를 작성하는 방법 내 게시물에서 아래 옵션에 대해 논의했습니다.

expected 매개변수 @Test(expected = FileNotFoundException.class) .

 @Test(expected = FileNotFoundException.class) public void testReadFile() { myClass.readFile("test.txt"); }

try catch 사용

 public void testReadFile() { try { myClass.readFile("test.txt"); fail("Expected a FileNotFoundException to be thrown"); } catch (FileNotFoundException e) { assertThat(e.getMessage(), is("The file test.txt does not exist!")); } }

ExpectedException 규칙으로 테스트합니다.

 @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testReadFile() throws FileNotFoundException { thrown.expect(FileNotFoundException.class); thrown.expectMessage(startsWith("The file test.txt")); myClass.readFile("test.txt"); }

예외 테스트 및 bad.robot-예외 JUnit 규칙에 대한 JUnit4 위키 에서 예외 테스트에 대해 자세히 읽을 수 있습니다.


Dilini Rajapaksha

같은 문제를 해결하기 위해 작은 프로젝트를 설정했습니다. http://code.google.com/p/catch-exception/

이 작은 도우미를 사용하면 다음과 같이 작성할 수 있습니다.

 verifyException(foo, IndexOutOfBoundsException.class).doStuff();

이것은 JUnit 4.7의 ExpectedException 규칙보다 덜 장황합니다. skaffman이 제공하는 솔루션과 비교하여 예외가 예상되는 코드 행을 지정할 수 있습니다. 이게 도움이 되길 바란다.


rwitzel

다음과 같이 할 수도 있습니다.

 @Test public void testFooThrowsIndexOutOfBoundsException() { try { foo.doStuff(); assert false; } catch (IndexOutOfBoundsException e) { assert true; } }

John Mikic

IMHO, JUnit에서 예외를 확인하는 가장 좋은 방법은 try/catch/fail/assert 패턴입니다.

 // this try block should be as small as possible, // as you want to make sure you only catch exceptions from your code try { sut.doThing(); fail(); // fail if this does not throw any exception } catch(MyException e) { // only catch the exception you expect, // otherwise you may catch an exception for a dependency unexpectedly // a strong assertion on the message, // in case the exception comes from anywhere an unexpected line of code, // especially important if your checking IllegalArgumentExceptions assertEquals("the message I get", e.getMessage()); }

assertTrue 는 어떤 사람들에게는 약간 assertThat(e.getMessage(), containsString("the message"); 가 더 나을 수 있습니다.


Alex Collins

Mkyong 블로그 에서 찾은 Junit 4에 대한 가장 유연하고 우아한 답변입니다. @Rule 주석을 사용하는 try/catch 의 유연성이 있습니다. 사용자 정의 예외의 특정 속성을 읽을 수 있기 때문에 이 접근 방식이 마음에 듭니다.

 package com.mkyong; import com.mkyong.examples.CustomerService; import com.mkyong.examples.exception.NameNotFoundException; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.hasProperty; public class Exception3Test { @Rule public ExpectedException thrown = ExpectedException.none(); @Test public void testNameNotFoundException() throws NameNotFoundException { //test specific type of exception thrown.expect(NameNotFoundException.class); //test message thrown.expectMessage(is("Name is empty!")); //test detail thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined. thrown.expect(hasProperty("errCode", is(666))); CustomerService cust = new CustomerService(); cust.findByName(""); } }

Dherik

JUnit 5 솔루션

 @Test void testFooThrowsIndexOutOfBoundsException() { IndexOutOfBoundsException exception = expectThrows(IndexOutOfBoundsException.class, foo::doStuff); assertEquals("some message", exception.getMessage()); }

http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions에서 JUnit 5에 대한 추가 정보


Daniel Käfer

여기에서 많은 방법을 시도했지만 복잡하거나 내 요구 사항을 충족하지 못했습니다. 사실, 아주 간단하게 도우미 메서드를 작성할 수 있습니다.

 public class ExceptionAssertions { public static void assertException(BlastContainer blastContainer ) { boolean caughtException = false; try { blastContainer.test(); } catch( Exception e ) { caughtException = true; } if( !caughtException ) { throw new AssertionFailedError("exception expected to be thrown, but was not"); } } public static interface BlastContainer { public void test() throws Exception; } }

다음과 같이 사용하십시오.

 assertException(new BlastContainer() { @Override public void test() throws Exception { doSomethingThatShouldExceptHere(); } });

종속성 없음: mockito가 필요 없고 powermock이 필요하지 않습니다. 최종 클래스에서 잘 작동합니다.


Hugh Perkins

JUnit은 "expected" 속성 과 함께 이에 대한 지원을 내장하고 있습니다.


Mark Bessey

자바 8 솔루션

다음과 같은 솔루션을 원할 경우:

  • Java 8 람다 활용
  • JUnit 마법에 의존 하지 않음
  • 단일 테스트 방법 내에서 여러 예외를 확인할 수 있습니다.
  • 전체 테스트 메서드에서 알 수 없는 줄 대신 테스트 메서드 내의 특정 줄 집합에서 예외가 발생하는지 확인합니다.
  • 더 자세히 조사할 수 있도록 throw된 실제 예외 개체를 생성합니다.

다음은 내가 작성한 유틸리티 함수입니다.

 public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable ) { try { runnable.run(); } catch( Throwable throwable ) { if( throwable instanceof AssertionError && throwable.getCause() != null ) throwable = throwable.getCause(); //allows testing for "assert x != null : new IllegalArgumentException();" assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown. assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected. @SuppressWarnings( "unchecked" ) T result = (T)throwable; return result; } assert false; //expected exception was not thrown. return null; //to keep the compiler happy. }

( 내 블로그에서 가져옴 )

다음과 같이 사용하십시오.

 @Test public void testMyFunction() { RuntimeException e = expectException( RuntimeException.class, () -> { myFunction(); } ); assert e.getMessage().equals( "I haz fail!" ); } public void myFunction() { throw new RuntimeException( "I haz fail!" ); }

Mike Nakis

제 경우에는 항상 db에서 RuntimeException을 받지만 메시지는 다릅니다. 그리고 예외는 각각 처리해야 합니다. 테스트한 방법은 다음과 같습니다.

 @Test public void testThrowsExceptionWhenWrongSku() { // Given String articleSimpleSku = "999-999"; int amountOfTransactions = 1; Exception exception = null; // When try { createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku); } catch (RuntimeException e) { exception = e; } // Then shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU); } private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) { assertNotNull(e); assertTrue(e.getMessage().contains(message)); }

Macchiatow

다음과 같이 끄고 켤 수 있는 Matcher를 만드십시오.

 public class ExceptionMatcher extends BaseMatcher<Throwable> { private boolean active = true; private Class<? extends Throwable> throwable; public ExceptionMatcher(Class<? extends Throwable> throwable) { this.throwable = throwable; } public void on() { this.active = true; } public void off() { this.active = false; } @Override public boolean matches(Object object) { return active && throwable.isAssignableFrom(object.getClass()); } @Override public void describeTo(Description description) { description.appendText("not the covered exception type"); } }

그것을 사용하려면:

추가 public ExpectedException exception = ExpectedException.none(); , 그 다음에:

 ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class); exception.expect(exMatch); someObject.somethingThatThrowsMyException(); exMatch.off();

Tor P

JUnit 4 이상에서는 다음과 같이 예외를 테스트할 수 있습니다.

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


이것은 JUnit 테스트를 개선하는 데 사용할 수 있는 많은 기능을 제공합니다.
아래 예를 보면 예외에 대해 3가지를 테스트하고 있습니다.

  1. 던져진 예외의 유형
  2. 예외 메시지
  3. 예외의 원인


 public class MyTest { @Rule public ExpectedException exceptions = ExpectedException.none(); ClassUnderTest classUnderTest; @Before public void setUp() throws Exception { classUnderTest = new ClassUnderTest(); } @Test public void testAppleisSweetAndRed() throws Exception { exceptions.expect(Exception.class); exceptions.expectMessage("this is the exception message"); exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause)); classUnderTest.methodUnderTest("param1", "param2"); } }

Jobin

예외를 반환해야 하는 메서드 다음에 assertion fail을 사용할 수 있습니다.

 try{ methodThatThrowMyException(); Assert.fail("MyException is not thrown !"); } catch (final Exception exception) { // Verify if the thrown exception is instance of MyException, otherwise throws an assert failure assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !"); // In case of verifying the error message MyException myException = (MyException) exception; assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage()); }

Shessuky

NamShubWriter가 말한 것 외에도 다음 을 확인하십시오.

  • ExpectedException 인스턴스가 공개됨 ( 관련 질문 )
  • ExpectedException은 @Before 메소드에서 인스턴스화 되지 않습니다.게시물 은 JUnit 실행 순서의 모든 복잡성을 명확하게 설명합니다.

이 작업을 수행하지 마십시오 :

 @Rule public ExpectedException expectedException; @Before public void setup() { expectedException = ExpectedException.none(); }

마지막으로 블로그 게시물은 특정 예외가 발생했다고 주장하는 방법을 명확하게 보여줍니다.


Srini

Java8이 포함된 Junit4 솔루션은 다음 기능을 사용하는 것입니다.

 public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) { try { funky.call(); } catch (Throwable e) { if (expectedException.isInstance(e)) { return e; } throw new AssertionError( String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e)); } throw new AssertionError( String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException)); }

사용법은 다음과 같습니다.

 assertThrows(ValidationException.class, () -> finalObject.checkSomething(null));

유일한 제한 사항은 람다 식에서 final @Test(expected = IndexOutOfBoundsException.class) 솔루션을 사용하여 메서드 수준에서 표시할 수 있을 것으로 기대하는 대신 테스트 어설션을 계속할 수 있습니다.


Donatello

junit 테스트에서 예외를 처리하기 위해 assertj-core 라이브러리를 권장합니다.

자바 8에서 다음과 같이:

 //given //when Throwable throwable = catchThrowable(() -> anyService.anyMethod(object)); //then AnyException anyException = (AnyException) throwable; assertThat(anyException.getMessage()).isEqualTo("........"); assertThat(exception.getCode()).isEqualTo(".......);

Piotr R

JUnit 프레임워크에는 assertThrows() 메소드가 있습니다.

 ArithmeticException exception = assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0)); assertEquals("/ by zero", exception.getMessage());

Lu55

예를 들어 아래에 언급된 코드 조각에 대해 Junit을 작성하려고 합니다.

 public int divideByZeroDemo(int a,int b){ return a/b; } public void exceptionWithMessage(String [] arr){ throw new ArrayIndexOutOfBoundsException("Array is out of bound"); }

위의 코드는 발생할 수 있는 알 수 없는 예외에 대해 테스트하는 것이고 아래는 사용자 정의 메시지로 일부 예외를 주장하는 코드입니다.

 @Rule public ExpectedException exception=ExpectedException.none(); private Demo demo; @Before public void setup(){ demo=new Demo(); } @Test(expected=ArithmeticException.class) public void testIfItThrowsAnyException() { demo.divideByZeroDemo(5, 0); } @Test public void testExceptionWithMessage(){ exception.expectMessage("Array is out of bound"); exception.expect(ArrayIndexOutOfBoundsException.class); demo.exceptionWithMessage(new String[]{"This","is","a","demo"}); }

Shirsh Sinha

Java 8을 사용하면 확인하는 코드와 예상되는 예외를 매개변수로 사용하는 메서드를 만들 수 있습니다.

 private void expectException(Runnable r, Class<?> clazz) { try { r.run(); fail("Expected: " + clazz.getSimpleName() + " but not thrown"); } catch (Exception e) { if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e); } }

그런 다음 테스트 내부에서 다음을 수행합니다.

 expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);

혜택:

  • 어떤 라이브러리에도 의존하지 않음
  • 현지화 검사 - 더 정확하고 필요한 경우 하나의 테스트 내에서 이와 같은 여러 어설션을 가질 수 있습니다.
  • 사용하기 쉬운

fahrenx

 @Test(expectedException=IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() throws Exception { doThrow(IndexOutOfBoundsException.class).when(foo).doStuff(); try { foo.doStuff(); } catch (IndexOutOfBoundsException e) { assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass()); throw e; } }

다음은 올바른 예외가 발생한 메서드를 확인하는 또 다른 방법입니다.


MangduYogii

출처 : http:www.stackoverflow.com/questions/156503/how-do-you-assert-that-a-certain-exception-is-thrown-in-junit-4-tests

반응형