Java 你如何断言在 JUnit 4 测试中抛出了某个异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/156503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you assert that a certain exception is thrown in JUnit 4 tests?
提问by SCdF
How can I use JUnit4 idiomatically to test that some code throws an exception?
如何惯用地使用 JUnit4 来测试某些代码是否引发异常?
While I can certainly do something like this:
虽然我当然可以做这样的事情:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
I recall that there is an annotation or an Assert.xyz or somethingthat is far less kludgy and far more in-the-spirit of JUnit for these sorts of situations.
我记得有一个注解或 Assert.xyz 或其他东西,对于这些类型的情况,JUnit 不那么笨拙,而且更具有 JUnit 的精神。
采纳答案by skaffman
It depends on the JUnit version and what assert libraries you use.
这取决于 JUnit 版本以及您使用的断言库。
- For JUnit5 and 4.13 see answer https://stackoverflow.com/a/2935935/2986984
- If you use assertJ or google-truth, see answer https://stackoverflow.com/a/41019785/2986984
- 对于 JUnit5 和 4.13,请参阅答案https://stackoverflow.com/a/2935935/2986984
- 如果您使用 assertJ 或 google-truth,请参阅答案 https://stackoverflow.com/a/41019785/2986984
The original answer for JUnit <= 4.12
was:
原来的答案JUnit <= 4.12
是:
@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
Though answer https://stackoverflow.com/a/31826781/2986984has more options for JUnit <= 4.12.
虽然回答https://stackoverflow.com/a/31826781/2986984为 JUnit <= 4.12 提供了更多选项。
Reference :
参考 :
回答by Johan
How about this: Catch a very general exception, make sure it makes it out of the catch block, then assert that the class of the exception is what you expect it to be. This assert will fail if a) the exception is of the wrong type (eg. if you got a Null Pointer instead) and b) the exception wasn't ever thrown.
怎么样:捕捉一个非常普遍的异常,确保它脱离了 catch 块,然后断言异常的类是你期望的。如果 a) 异常类型错误(例如,如果您使用空指针)并且 b) 从未抛出异常,则此断言将失败。
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
回答by Mark Bessey
JUnit has built-in support for this, with an "expected" attribute
JUnit 对此具有内置支持,带有“预期”属性
回答by daveb
Be careful using expected exception, because it only asserts that the methodthrew that exception, not a particular line of codein the test.
使用预期异常时要小心,因为它只断言该方法抛出了该异常,而不是测试中的特定代码行。
I tend to use this for testing parameter validation, because such methods are usually very simple, but more complex tests might better be served with:
我倾向于使用它来测试参数验证,因为这些方法通常非常简单,但更复杂的测试可能更好地用于:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
Apply judgement.
应用判断。
回答by NamshubWriter
Edit:Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows()
(for JUnit 5) and Assert.assertThrows()
(for JUnit 4.13). See my other answerfor details.
编辑:现在 JUnit 5 和 JUnit 4.13 已经发布,最好的选择是使用Assertions.assertThrows()
(对于 JUnit 5)和Assert.assertThrows()
(对于 JUnit 4.13)。有关详细信息,请参阅我的另一个答案。
If you haven't migrated to JUnit 5, but can use JUnit 4.7, you can use the ExpectedException
Rule:
如果您还没有迁移到 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();
}
}
This is much better than @Test(expected=IndexOutOfBoundsException.class)
because the test will fail if IndexOutOfBoundsException
is thrown before foo.doStuff()
这比@Test(expected=IndexOutOfBoundsException.class)
因为如果IndexOutOfBoundsException
之前抛出测试将失败要好得多foo.doStuff()
See this articlefor details
请参见本文的详细信息
回答by rwitzel
To solve the same problem I did set up a small project: http://code.google.com/p/catch-exception/
为了解决同样的问题,我确实建立了一个小项目:http: //code.google.com/p/catch-exception/
Using this little helper you would write
使用这个小帮手你会写
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
This is less verbose than the ExpectedException rule of JUnit 4.7. In comparison to the solution provided by skaffman, you can specify in which line of code you expect the exception. I hope this helps.
这比 JUnit 4.7 的 ExpectedException 规则更简洁。与 skaffman 提供的解决方案相比,您可以指定期望异常出现在哪一行代码中。我希望这有帮助。
回答by Hugh Perkins
I tried many of the methods here, but they were either complicated or didn't quite meet my requirements. In fact, one can write a helper method quite simply:
我在这里尝试了很多方法,但它们要么很复杂,要么不太符合我的要求。事实上,可以非常简单地编写一个辅助方法:
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;
}
}
Use it like this:
像这样使用它:
assertException(new BlastContainer() {
@Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
Zero dependencies: no need for mockito, no need powermock; and works just fine with final classes.
零依赖:不需要mockito,不需要powermock;并且在最后的课程中工作得很好。
回答by John Mikic
You can also do this:
你也可以这样做:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
回答by Tor P
Just make a Matcher that can be turned off and on, like this:
只需制作一个可以关闭和打开的匹配器,如下所示:
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");
}
}
To use it:
要使用它:
add public ExpectedException exception = ExpectedException.none();
,
then:
添加public ExpectedException exception = ExpectedException.none();
,然后:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
回答by Macchiatow
In my case I always get RuntimeException from db, but messages differ. And exception need to be handled respectively. Here is how I tested it:
在我的情况下,我总是从 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));
}