当 JUnit 测试抛出异常时,我应该如何捕获对象状态?
我在 JUnit 中设置了一个简单的测试,类似于
public void testGetBar() throws MyException{
Foo f = new Foo();
f.setup();
assertEquals(new Bar("1234"), f.getBar());
}
假设 getBar()
引发了 MyException
:JUnit 将此记录为“错误”测试,我注意到我搞砸了这个方法。是的,单元测试有效!但是,我无法知道我的 Foo 对象出了什么问题,当我尝试对其进行 getBar()
时,它会抛出异常,而无需返回并例如通过调试器运行测试,或者添加日志记录语句。每个人都说在 JUnit 测试中捕获异常是一个坏主意,所以这样做似乎很笨拙:
try{
assertEquals(new Bar("1234"), f.getBar());
} catch(MyException e) {
log.error(f.toString());
throw e;
}
但这就是我能想到的。是否没有 JUnit-y 的简写形式说“当此测试中出现异常时,(以某种方式)注销这个、那个和其他对象状态”,以便轻松找出问题所在?
I have a simple test set up in JUnit, along the lines of
public void testGetBar() throws MyException{
Foo f = new Foo();
f.setup();
assertEquals(new Bar("1234"), f.getBar());
}
Suppose getBar()
threw a MyException
: JUnit notes this as a test "in error", and I notice that I screwed up the method. Yay, unit testing works! However, I have no way of knowing what was wrong with my Foo object that made it throw when I tried to getBar()
on it, without going back and e.g. running the test through a debugger, or adding a logging statement. Everybody says it's a bad idea catch exceptions in your JUnit tests, so it seems hamfisted to do this:
try{
assertEquals(new Bar("1234"), f.getBar());
} catch(MyException e) {
log.error(f.toString());
throw e;
}
but it's all I can think of. Is there no JUnit-y shorthand of saying "when there's an exception in this test, log out this, that, and the other object state (somehow)" to make it easy to figure out where things went wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您应该提高抛出的异常中的信息质量,以便您能够了解单元测试中出了什么问题。这确保了以后如果在生产中抛出异常,您将获得有用的异常消息,而不是一些神秘的消息。
我不确定你为什么要有条件地记录异常。 单元测试应该始终通过或始终抛出异常。如果您希望出现异常,请添加注释
@Test(expection=Exception.class)
如果您确实想记录异常,最优雅的方法是使用
@RunWith( MyRunner.class)
并创建一个类MyRunner extends BlockJUnit4Runner
来处理日志记录。You should improve the quality of information in the exceptions you throw so that you can understand what went wrong in the unit test. This ensures that later if an exception is thrown in production you will have a useful exception message rather than something cryptic.
I'm not sure why you want to conditionally log exceptions. A unit test should always pass or always throw an exception. If you want to expect an Exception add the Annotation
@Test(expection=Exception.class)
If you really want to log exceptions the most elegant way is to annotate your test class with
@RunWith(MyRunner.class)
and create a classMyRunner extends BlockJUnit4Runner
that handles the logging.您不会将所有单元测试代码包装在异常处理程序中:仅将您遇到问题的代码包装起来。让 JUnit 捕获意外异常作为错误也很好:当发生这种情况并且您正在调查问题时,将有问题的代码包装在处理程序中(然后再次删除)。
不过,这应该是相当罕见的:在进行单元测试时,您不希望代码抛出随机异常(单元测试应该尽可能干净且可重复)。
当然,您也需要对异常生成进行单元测试:在这种情况下,您肯定希望将对有问题的函数的调用包装在处理程序中,然后在异常没有发生时抛出fail()。
You wouldn't wrap all your unit testing code in exception handlers: just the ones your having trouble with. Leaving JUnit to catch unanticipated exceptions as errors is also fine: wrap the offending code in a handler when that happens and you're investigating the problem (then remove again).
This should all be fairly infrequent though: you don't want code that throws random exceptions when you're unit testing (which should be as clean and repeatable as possible).
Of course, you will want to unit test your exception generation too: in which case you will definitely want to wrap the call to the offending function in a handler, then throw a fail() if the exception does not occur.