질문자 :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 BorowiecJunit에는 예외를 테스트하는 네 가지 방법이 있습니다.
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헐 박사
Junit 4 또는 JUnit 5에 관계없이.
긴 이야기
자신에게 쓸 수있는 그것을 할 자신이 try
- catch
블록 또는 JUnit을 도구 (사용 @Test(expected = ...)
또는 @Rule ExpectedException
의 JUnit 규칙 기능).
그러나 이러한 방법은 그다지 우아하지 않으며 다른 도구와 가독성이 좋지 않습니다. 또한 JUnit 도구에는 몇 가지 함정이 있습니다.
try
- catch
블록 테스트된 동작 주위에 블록을 작성하고 catch 블록에 어설션을 작성해야 합니다. 괜찮을 수 있지만 많은 사람들은 이 스타일이 테스트의 읽기 흐름을 방해한다는 것을 알게 됩니다. try
블록 끝에 Assert.fail
을 작성해야 합니다. 그렇지 않으면 테스트에서 주장의 한 쪽이 누락될 수 있습니다. PMD , findbugs 또는 Sonar 가 이러한 문제를 찾아낼 것입니다.
@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 }
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을 사용하면 오류가 발생하기 쉽습니다.
따라서 위의 이러한 옵션에는 모든 주의 사항이 있으며 분명히 코더 오류에 영향을 받지 않습니다.
유망해 보이는 이 답변을 만든 후 알게 된 프로젝트가 있습니다. 그것은 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 지원을 양조하는 것 같습니다.
현재 이 라이브러리에는 두 가지 단점이 있습니다.
라이브러리가 람다를 지원하면 이러한 문제가 적용되지 않습니다. 그러나 기능은 AssertJ 도구 집합에 의해 복제됩니다.
catch-exception 도구를 사용하고 싶지 않다면 모든 것을 고려하여 적어도 JDK7까지는 try
- catch
그리고 JDK 8 사용자의 경우 AssertJ를 사용하는 것을 선호할 수 있습니다.
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"); }
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!"); } }
다른 답변의 접근 방식에 비해 장점은 다음과 같습니다.
- JUnit에 내장
- 람다의 코드에서 예외가 발생하지 않으면 유용한 예외 메시지가 표시되고, 다른 예외가 발생하면 스택 추적이 표시됩니다.
- 간결한
- 테스트가 Arrange-Act-Assert를 따르도록 허용합니다.
- 예외를 던질 것으로 예상되는 코드를 정확하게 나타낼 수 있습니다.
-
throws
절에 예상되는 예외를 나열할 필요가 없습니다. - 선택한 어설션 프레임워크를 사용하여 catch된 예외에 대한 어설션을 만들 수 있습니다.
NamshubWriter이것은 어떻습니까? 매우 일반적인 예외를 잡아서 catch 블록에서 벗어나도록 한 다음 예외의 클래스가 예상한 것과 같은지 확인하십시오. 이 주장은) 예외가 잘못된 유형이고(예: 대신 Null 포인터가 있는 경우) b) 예외가 발생하지 않은 경우 실패합니다.
public void testFooThrowsIndexOutOfBoundsException() { Throwable e = null; try { foo.doStuff(); } catch (Throwable ex) { e = ex; } assertTrue(e instanceof IndexOutOfBoundsException); }
JohanJUnit과 함께 사용할 수 있는 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 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 MikicIMHO, 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 CollinsMkyong 블로그 에서 찾은 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(""); } }
DherikJUnit 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 PerkinsJUnit은 "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 PJUnit 4 이상에서는 다음과 같이 예외를 테스트할 수 있습니다.
@Rule public ExpectedException exceptions = ExpectedException.none();
이것은 JUnit 테스트를 개선하는 데 사용할 수 있는 많은 기능을 제공합니다.
아래 예를 보면 예외에 대해 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()); }
ShessukyNamShubWriter가 말한 것 외에도 다음 을 확인하십시오.
- ExpectedException 인스턴스가 공개됨 ( 관련 질문 )
- ExpectedException은 @Before 메소드에서 인스턴스화 되지 않습니다. 이 게시물 은 JUnit 실행 순서의 모든 복잡성을 명확하게 설명합니다.
이 작업을 수행하지 마십시오 :
@Rule public ExpectedException expectedException; @Before public void setup() { expectedException = ExpectedException.none(); }
마지막으로 이 블로그 게시물은 특정 예외가 발생했다고 주장하는 방법을 명확하게 보여줍니다.
SriniJava8이 포함된 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)
솔루션을 사용하여 메서드 수준에서 표시할 수 있을 것으로 기대하는 대신 테스트 어설션을 계속할 수 있습니다.
Donatellojunit 테스트에서 예외를 처리하기 위해 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 RJUnit 프레임워크에는 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 SinhaJava 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