如何使用 JUnit Test 注释断言异常消息?
我用 @Test
注释编写了一些 JUnit 测试。如果我的测试方法抛出一个已检查的异常,并且我想断言消息和异常,有没有办法使用 JUnit @Test
注释来做到这一点? AFAIK,JUnit 4.7 不提供此功能,但未来的版本是否提供此功能?我知道在 .NET 中您可以断言消息和异常类。在 Java 世界中寻找类似的功能。
这就是我想要的:
@Test (expected = RuntimeException.class, message = "Employee ID is null")
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() {}
I have written a few JUnit tests with @Test
annotation. If my test method throws a checked exception and if I want to assert the message along with the exception, is there a way to do so with JUnit @Test
annotation? AFAIK, JUnit 4.7 doesn't provide this feature but does any future versions provide it? I know in .NET you can assert the message and the exception class. Looking for similar feature in the Java world.
This is what I want:
@Test (expected = RuntimeException.class, message = "Employee ID is null")
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() {}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
您可以使用
@Rule
注释ExpectedException
,如下所示:
ExpectedException
文档中的示例(当前)是错误的 - 没有公共构造函数,因此您必须使用ExpectedException.none()
。You could use the
@Rule
annotation withExpectedException
, like this:Note that the example in the
ExpectedException
docs is (currently) wrong - there's no public constructor, so you have to useExpectedException.none()
.在 JUnit 4.13 中,您可以执行以下操作:
这也适用于 JUnit 5< /a> 但具有不同的导入:
In JUnit 4.13 you can do:
This also works in JUnit 5 but with different imports:
我喜欢
@Rule
答案。但是,如果由于某种原因您不想使用规则。还有第三种选择。I like the
@Rule
answer. However, if for some reason you don't want to use rules. There is a third option.您必须使用@Test(expected=SomeException.class)吗?当我们必须断言异常的实际消息时,这就是我们所做的。
Do you have to use
@Test(expected=SomeException.class)
? When we have to assert the actual message of the exception, this is what we do.实际上,最好的用法是与 try/catch 一起使用。为什么?因为你可以控制你期望发生异常的地方。
考虑这个例子:
如果有一天代码被修改并且测试准备将抛出 RuntimeException 怎么办?在这种情况下,实际测试甚至没有经过测试,即使它没有抛出任何异常,测试也会通过。
这就是为什么使用 try/catch 比依赖注释要好得多。
Actually, the best usage is with try/catch. Why? Because you can control the place where you expect the exception.
Consider this example:
What if one day the code is modified and test preparation will throw a RuntimeException? In that case actual test is not even tested and even if it doesn't throw any exception the test will pass.
That is why it is much better to use try/catch than to rely on the annotation.
我从来不喜欢使用 Junit 断言异常的方式。如果我在注释中使用“预期”,从我的角度来看,我们似乎违反了“给定、何时、然后”模式,因为“然后”被放置在测试定义的顶部。
另外,如果我们使用“@Rule”,我们就必须处理如此多的样板代码。所以,如果你可以为你的测试安装新的库,我建议看看 AssertJ (该库现在随 SpringBoot 一起提供)
然后一个不违反“given/when/then”原则的测试,它使用 AssertJ 来验证:
1 - 异常是我们所期望的。
2 - 它还有一条预期消息,
如下所示:
I never liked the way of asserting exceptions with Junit. If I use the "expected" in the annotation, seems from my point of view we're violating the "given, when, then" pattern because the "then" is placed at the top of the test definition.
Also, if we use "@Rule", we have to deal with so much boilerplate code. So, if you can install new libraries for your tests, I'd suggest to have a look to the AssertJ (that library now comes with SpringBoot)
Then a test which is not violating the "given/when/then" principles, and it is done using AssertJ to verify:
1 - The exception is what we're expecting.
2 - It has also an expected message
Will look like this:
Raystorm 有一个很好的答案。我也不太喜欢规则。我做了类似的事情,只是我创建了以下实用程序类来帮助提高可读性和可用性,这首先是注释的一大优点。
添加此实用程序类:
然后对于我的单元测试,我只需要以下代码:
Raystorm had a good answer. I'm not a big fan of Rules either. I do something similar, except that I create the following utility class to help readability and usability, which is one of the big plus'es of annotations in the first place.
Add this utility class:
Then for my unit test, all I need is this code:
假设我们在
FooService
类中有一个方法doStuff
。当参数中传递 null 标志时,此方法可能会引发 NullPointerException。使用 Junit 5
Junit 5
assertThrows
返回异常,可用于断言异常消息,如下例所示: -使用 AssertJ
AssertJ 有各种断言来测试异常,其中之一是
assertThatRuntimeException 可以与
withMessage
链接来测试异常消息Let's say, we have a method
doStuff
in the classFooService
. This method can throw a NullPointerException when a null flag is passed in the argument.Using Junit 5
Junit 5
assertThrows
returns exception, which can be used to assert exception message as per below example:-Using AssertJ
AssertJ has various assertions to test exception, one of them is
assertThatRuntimeException
which can be chained withwithMessage
to test exception message我更喜欢 AssertJ 。
I would prefer AssertJ for this.
如果使用 @Rule,则异常集将应用于 Test 类中的所有测试方法。
If using @Rule, the exception set is applied to all the test methods in the Test class.
我喜欢 user64141 的答案,但发现它可以更普遍。这是我的看法:
请注意,在 try 块中保留“fail”语句会导致相关的断言异常被捕获;在 catch 语句中使用 return 可以防止这种情况发生。
I like user64141's answer but found that it could be more generalized. Here's my take:
Note that leaving the "fail" statement within the try block causes the related assertion exception to be caught; using return within the catch statement prevents this.
导入 catch-exception 库并使用它。它比
ExpectedException
规则或try-catch
干净得多。他们的文档示例:
Import the catch-exception library, and use that. It's much cleaner than the
ExpectedException
rule or atry-catch
.Example form their docs: