JUnit 4 테스트에서 특정 예외가 발생한다고 주장하는 방법은 무엇입니까?
JUnit4를 사용하여 일부 코드가 예외를 발생시키는 것을 테스트하려면 어떻게 해야 합니까?
물론 이런 건 할 수 있지만
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
나는 주석이나 Assert.xyz 같은 것이 이러한 상황에서 훨씬 덜 거칠고 훨씬 더 정신적인 것이라고 기억한다.
JUnit 버전과 사용하는 아사트 라이브러리에 따라 달라집니다.
- JUnit5 및 4.13에 대해서는, 회답 https://stackoverflow.com/a/2935935/2986984 를 참조해 주세요.
- assertJ 또는 google-truth를 사용하는 경우 답변 https://stackoverflow.com/a/41019785/2986984을 참조하십시오.
에 대한 원래 답변은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에 대한 옵션이 더 있습니다.
레퍼런스:
편집: JUnit 5와 JUnit 4.13이 출시되었으므로 JUnit 5와 JUnit 4.13+를 사용하는 것이 가장 좋습니다.자세한 내용은 다른 답변을 참조하십시오.
JUnit 5로 마이그레이션하지 않았지만 JUnit 4.7을 사용할 수 있는 경우 규칙을 사용할 수 있습니다.
public class FooTest {
@Rule
public final ExpectedException exception = ExpectedException.none();
@Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
}
}
면 좋다, 좋다, , 이런 얘기죠?@Test(expected=IndexOutOfBoundsException.class)
이 하기 때문이다.IndexOutOfBoundsException
에 던져지다foo.doStuff()
메서드가 테스트에서 특정 코드 행이 아닌 해당 예외를 발생시켰다고 주장할 뿐이므로 예상된 예외를 사용할 때는 주의하십시오.
파라미터 검증 테스트에는 이 방법을 사용하는 경향이 있습니다.이러한 방법은 보통 매우 간단하지만 보다 복잡한 테스트는 다음과 같이 실시하는 것이 좋습니다.
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
판단을 내리다.
앞서 답변했듯이 JUnit의 예외에 대처하는 방법은 여러 가지가 있습니다.그러나 Java 8에는 또 다른 방법이 있습니다. 람다 익스프레션을 사용하는 것입니다.Lambda Expressions를 사용하면 다음과 같은 구문을 얻을 수 있습니다.
@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 에서 찾을 수 있습니다.
공개:저는 블로그와 프로젝트의 저자입니다.
junit에서는 예외를 테스트하는 4가지 방법이 있습니다.
junit 5.x
5. junit 5.x를 사용할 수 .
assertThrows
과 같이@Test public void testFooThrowsIndexOutOfBoundsException() { Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff()); assertEquals("expected messages", exception.getMessage()); }
junit 4.x
junit4.x의 경우 Test annonation의 옵션인 'expected' 속성을 사용합니다.
@Test(expected = IndexOutOfBoundsException.class) public void testFooThrowsIndexOutOfBoundsException() { foo.doStuff(); }
junit4.x 의 경우는, 「예상」을 사용합니다.예외 규칙
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 프레임워크에서 널리 사용되는 고전적인 시도/정지 방법을 사용할 수도 있습니다.
@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 유저 가이드를 참조해 주세요.
dr;dr
post-JDK8 : AssertJ 또는 커스텀램다를 사용하여 예외적인 동작을 강조합니다.
: JDK8을 합니다.
try
-catch
block. (블록 앞에 어설션을 추가하는 것을 잊지 마세요)
Junit 4나 JUNIT 5에 상관없이.
긴 이야기
스스로 그것을 할 수 있다. try
-catch
또는 도구 (JUnit )@Test(expected = ...)
★★★@Rule ExpectedException
JUnit 칙 ju ju ( JUnit " 。
그러나 이러한 방식은 그다지 우아하지 않고 읽기 쉬운 다른 도구와 함께 사용할 수 없습니다.게다가 JUnit 툴링에는 몇 가지 함정이 있습니다.
try
-catch
블록은 테스트된 동작 주위에 블록을 쓰고 어설션을 캐치 블록에 적어야 합니다. 이는 괜찮을 수 있지만 많은 사람들이 이 스타일이 테스트의 읽기 흐름을 방해한다는 것을 발견합니다.아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아,Assert.fail
try
차단. 그렇지 않으면, PMD, findbugs 또는 Sonar가 이러한 문제를 발견하게 됩니다.@Test(expected = ...)
이 기능은 코드를 적게 쓸 수 있기 때문에 흥미롭습니다.그러면 이 테스트를 쓰는 것은 아마 코드화 오류가 발생할 가능성이 낮아집니다.그러나 일부 지역에서는 이 접근법이 부족하다.- 테스트에서 예외에 대해 원인이나 메시지와 같은 추가 사항을 확인해야 하는 경우(좋은 예외 메시지가 매우 중요함), 정확한 예외 유형을 갖는 것만으로는 충분하지 않을 수 있습니다.
또한 테스트된 코드가 어떻게 쓰여지는지에 따라 테스트 코드의 잘못된 부분이 예외를 던질 수 있으며, 이는 잘못된 양성 테스트로 이어질 수 있으며 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(Behavior Driven Development) 또는 AAA(Array Act Assert) 원칙을 따르면ExpectedException
그 작문 스타일에는 규칙이 맞지 않는다.과는 별도로, 그것은 「아까의 문제」와 있을 .@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를 따를 경우 판독 플로우가 중단됩니다.
또, 이 코멘트는, 의 저자의 JUnit에 게재되어 있는 것을 참조해 주세요.
ExpectedException
. JUnit 4.13-beta-2에서는 이 메커니즘도 권장되지 않습니다.Assert.assert 메서드예외를 검증하기 위한 보다 좋은 방법을 제공합니다.또한 Expected의 사용예외는 규칙 순서가 중요하기 때문에 TestWatcher와 같은 다른 규칙과 함께 사용하면 오류가 발생하기 쉽습니다.
따라서 위의 옵션에는 경고의 부하가 모두 포함되어 있어 코더 에러의 영향을 받지 않습니다.
제가 이 답을 만들고 나서 알게 된 프로젝트가 있는데, 그것은 바로 캐치-익스펙션입니다.
프로젝트의 설명에 있듯이, 코더는 예외를 포착하는 코드의 유창한 행으로 기술할 수 있으며, 후자의 어설션에는 이 예외를 제공합니다.또한 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();
코드가 간단하다는 을 알 수 있듯이, '를 특정. '예외를 잡다', '예외로 하다', '예외로 하다', '예외로 하다', '예외로하다', '예외로 하다', '예외로 하다', '예외로하다.
then
는 AssertJ AssertJ API를 사용하는 것과 합니다).assertThat(ex).hasNoCause()...
AssertJ의 조상인 FEST-Assert에 의존한 프로젝트도 있습니다.편집: 이 프로젝트는 Java 8 Lambdas의 지원을 받고 있는 것 같습니다.현재 이 라이브러리에는 두 가지 단점이 있습니다.
이 글을 쓸 때, 이 라이브러리는 이면에서 테스트 대상물을 조롱하는 모키토 1.x를 기반으로 하고 있다는 점에서 주목할 만하다.Mockito가 아직 업데이트되지 않았기 때문에 이 라이브러리는 최종 클래스 또는 최종 메서드로 작동할 수 없습니다.그리고 현재 버전에서는 Mockito 2를 기반으로 하고 있었다고 해도, 이것은 글로벌 모크 메이커를 선언할 필요가 있다.
inline-mock-maker
이 모크 메이커는 일반 모크 메이커와 다른 단점을 가지고 있기 때문에, 당신이 원하는 것은 아닐지도 모릅니다.또 다른 테스트 의존성이 필요합니다.
라이브러리가 람다를 지원하면 이러한 문제는 적용되지 않습니다.단, 이 기능은 AssertJ 툴셋에 의해 복제됩니다.
툴을 않은 는, 「 툴」의 합니다.
try
-catch
「JDK7」, 「JDK7」.또한 JDK 8 사용자에게는 AssertJ가 제공하는 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의 거의 완전한 개서에서는 어설션이 약간 개선되어 적절한 예외를 어설션하기 위한 새로운 방법으로 흥미로운 것으로 판명될 수 있습니다.하지만 실제로 어설션 API는 아직 조금 빈약합니다.외부에는 아무것도 없다.
@Test @DisplayName("throws EmptyStackException when peeked") void throwsExceptionWhenPeeked() { Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek()); Assertions.assertEquals("...", t.getMessage()); }
눈치채셨듯이
assertEquals
있다void
Assert J는 Assert J를 사용합니다., 가 「」와 격돌하는 것을 하고 있는 .
Matcher
★★★★★★★★★★★★★★★★★」Assert
는, 「」와 에 대비하고Assertions
.
오늘(2017-03-03) AssertJ의 사용 편의성, 발견 가능한 API, 빠른 개발 속도 및 사실상의 테스트 의존성이 테스트 프레임워크(JUnit 또는 JUnit)에 관계없이 JDK8을 사용하는 최고의 솔루션이라는 결론을 내리고 싶습니다.그 대신 기존 JDK는 블록에 catch
의존해야 합니다.
이 답변은 다른 질문에서 베낀 것입니다. 동일한 작성자입니다.
5 및4.되었으므로 JUnit 5.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에 내장
- lamda의 코드가 예외를 슬로우하지 않으면 유용한 예외 메시지가 표시되고 다른 예외를 슬로우하면 스택 트레이스가 표시됩니다.
- 간결하다.
- 테스트를 정렬-행동-어세트에 따르도록 합니다.
- 예외를 발생시킬 것으로 예상되는 코드를 정확하게 지정할 수 있습니다.
- '예상했던 예외'는 굳이 '했던 예외'를
throws
삭제 - 선택한 어설션 프레임워크를 사용하여 탐지된 예외에 대한 어설션을 수행할 수 있습니다.
이것은 어떨까요? 매우 일반적인 예외를 포착하고, 그것이 캐치 블록에서 벗어나는지 확인한 다음, 예외의 클래스가 여러분이 예상하는 것과 같다고 주장합니다.a) 예외가 잘못된 유형(예: Null 포인터를 받은 경우)이고 b) 예외가 느려지지 않은 경우 이 주장은 실패합니다.
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
업데이트: 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!"));
}
}
에한 testing testing testingExpectedException
@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 - Exceptions JUnit Rule에 대한 예외 테스트에 대한 자세한 내용은 JUnit4 Wiki에서 확인할 수 있습니다.
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");
BDD 스타일 솔루션: JUnit 4 + 어획 예외 + Assert J
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
같은 문제를 해결하기 위해 작은 프로젝트를 세웠습니다.http://code.google.com/p/catch-exception/
이 작은 도우미를 이용해서
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
이것은 예상된 것보다 덜 상세합니다.JUnit 4.7의 예외 규칙.skaffman이 제공하는 솔루션과 비교하여 예외를 예상하는 코드 행을 지정할 수 있습니다.이게 도움이 됐으면 좋겠어요.
다음 작업도 수행할 수 있습니다.
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
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");
더 좋을 수도 있습니다.
Mkyong 블로그에서 찾은 Junit 4에 대한 가장 유연하고 우아한 답변.유연성이 있습니다.try/catch
@Rule
수 때문에 요.커스터마이즈된 예외의 특정 속성을 읽을 수 있기 때문에 이 접근방식이 마음에 듭니다.
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("");
}
}
JUnit 5 솔루션
@Test
void testFooThrowsIndexOutOfBoundsException() {
IndexOutOfBoundsException exception = expectThrows(IndexOutOfBoundsException.class, foo::doStuff);
assertEquals("some message", exception.getMessage());
}
JUnit 5에 대한 자세한 내용은 http://junit.org/junit5/docs/current/user-guide/ #writing-discriptions 。
저는 여기서 많은 방법을 시도했지만, 그것들은 복잡하거나 제 요구 사항에 맞지 않았습니다.실제로 도우미 메서드는 다음과 같이 간단하게 작성할 수 있습니다.
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();
}
});
의존관계 없음: 모키토도 필요 없고 파워모크도 필요 없습니다.최종 수업에서도 문제없이 동작합니다.
JUnit에는 "예상된" 속성을 가진 기본 지원 기능이 있습니다.
Java 8 솔루션
다음과 같은 솔루션을 원하는 경우:
- Java 8 람다 사용
- JUnit 마법에 의존하지 않음
- 단일 테스트 방법 내에서 여러 예외를 확인할 수 있습니다.
- 전체 테스트 메서드에서 알 수 없는 행 대신 테스트 메서드 내의 특정 행 집합에 의해 예외가 발생하는지 확인합니다.
- 더 자세히 검토할 수 있도록 던져진 실제 예외 개체를 생성합니다.
다음은 제가 작성한 유틸리티 함수입니다.
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!" );
}
내 경우 항상 Runtime이 표시됩니다.db의 예외이지만 메시지가 다릅니다.그리고 예외는 각각 처리해야 합니다.테스트 방법은 다음과 같습니다.
@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));
}
이렇게 껐다가 켤 수 있는 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();
JUnit 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");
}
}
예외를 반환해야 하는 메서드 뒤에 어설션 실패를 사용할 수 있습니다.
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());
}
NamShubWriter가 말한 내용과 더불어 다음 사항을 확인합니다.
- 예기된 것예외 인스턴스는 공개(관련 질문)
- 예기된 것예외는 예를 들어 @Before 메서드에서 인스턴스화되지 않습니다.이 글은 JUnit의 사형 집행 순서에 대한 모든 복잡한 내용을 명확하게 설명하고 있다.
이 조작은 하지 말아 주세요.
@Rule
public ExpectedException expectedException;
@Before
public void setup()
{
expectedException = ExpectedException.none();
}
마지막으로, 이 블로그 투고에서는 특정 예외가 발생했다고 주장하는 방법을 명확하게 설명하고 있습니다.
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)
★★★★★★★★★★★★★★★★★★.
는 도서관을 합니다.assertj-core
에
Java 8에서는 다음과 같습니다.
//given
//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));
//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
JUnit 프레임워크에는 다음과 같은 방법이 있습니다.
ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
- JUnit 5는 수업 중이고,
- JUnit 4.13은 수업 중.
- JUnit 4 이전 버전: 프로젝트에 참조만 추가하면 JUnit 5에서 완벽하게 작동하는 버전을 얻을 수 있습니다.
예를 들어, 아래에 언급된 코드 조각에 대해 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"});
}
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);
이점:
- 어떤 도서관에도 의존하지 않는다
- 국부 검사 - 더 정밀하고 필요할 경우 한 번의 테스트 내에서 이와 같은 여러 주장을 할 수 있다.
- 사용하기 쉽다
@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;
}
}
다음은 올바른 예외가 발생했는지 여부를 확인하는 다른 방법입니다.
언급URL : https://stackoverflow.com/questions/156503/how-do-you-assert-that-a-certain-exception-is-thrown-in-junit-4-tests
'programing' 카테고리의 다른 글
EXE 또는 MSI 설치가 아닌 zip 파일로 최신 JRE/JDK를 입수하려면 어떻게 해야 합니까? (0) | 2022.08.27 |
---|---|
렌더링 전에 비동기 데이터를 대기할 구성 요소 가져오기 (0) | 2022.08.27 |
vue-cli 웹 팩 인코딩 이미지 base64 사용 안 함 (0) | 2022.08.27 |
Java를 사용하여 정규 표현을 사용하여 더 큰 문자열의 하위 문자열 검색 (0) | 2022.08.27 |
HTML 파일에서 Vue div로 HTML 로드 (0) | 2022.08.27 |