如何测试没有抛出异常? [英] How to test that no exception is thrown?

查看:131
本文介绍了如何测试没有抛出异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道一种方法是:

@Test
public void foo(){
   try{
      //execute code that you expect not to throw Exceptions.
   }
   catch(Exception e){
      fail("Should not have thrown any exception");
   }
}

有没有更清洁的方法。 (可能使用Junit的 @Rule ?)

Is there any cleaner way of doing this. (Probably using Junit's @Rule?)

推荐答案

你即将到来这是错误的方式。只测试您的功能:如果抛出异常,测试将自动失败。如果没有抛出任何异常,你的测试都将变为绿色。

You're approaching this the wrong way. Just test your functionality: if an exception is thrown the test will automatically fail. If no exception is thrown, your tests will all turn up green.

我注意到这个问题不时引起人们的兴趣,所以我会稍微扩展一下。

I have noticed this question garners interest from time to time so I'll expand a little.

当您进行单元测试时,重要的是要自己定义您认为的单元测试单位工作。基本上:提取您的代码库,可能包含也可能不包含代表单个功能的多个方法或类。

When you're unit testing it's important to define to yourself what you consider a unit of work. Basically: an extraction of your codebase that may or may not include multiple methods or classes that represents a single piece of functionality.

或者,如单元测试的艺术,Roy Osherove的第2版,第11页:


单元测试是一段自动代码,用于调用正在测试的工作单元,然后检查有关单个最终结果的一些假设单元。单元测试几乎总是使用单元测试框架编写。它可以轻松编写并快速运行。它值得信赖,易读且易于维护。只要生产代码没有改变,它的结果就是一致的。

A unit test is an automated piece of code that invokes the unit of work being tested, and then checks some assumptions about a single end result of that unit. A unit test is almost always written using a unit testing framework. It can be written easily and runs quickly. It's trustworthy, readable, and maintainable. It's consistent in its results as long as production code hasn't changed.

重要的是要知道一个单位工作通常不仅仅是一种方法,但在最基本的层面上它是一种方法,之后它被其他工作单元封装。

What is important to realize is that one unit of work usually isn't just one method but at the very basic level it is one method and after that it is encapsulated by other unit of works.

理想情况下,你应该有一个每个单独工作单元的测试方法,这样您就可以随时查看出错的地方。在这个例子中有一个名为 getUserById()的基本方法,它将返回一个用户,总共有3个单位的作品。

Ideally you should have a test method for each separate unit of work so you can always immediately view where things are going wrong. In this example there is a basic method called getUserById() which will return a user and there is a total of 3 unit of works.

第一个工作单元应测试在有效和无效输入的情况下是否返回有效用户。

数据源抛出的任何异常都必须是这里处理:如果没有用户,那么应该有一个测试,证明当找不到用户时会抛出异常。这样的示例可能是 IllegalArgumentException ,它被 @Test(expected = IllegalArgumentException.class)注释捕获。

The first unit of work should test whether or not a valid user is being returned in the case of valid and invalid input.
Any exceptions that are being thrown by the datasource have to be handled here: if no user is present there should be a test that demonstrates that an exception is thrown when the user can't be found. A sample of this could be the IllegalArgumentException which is caught with the @Test(expected = IllegalArgumentException.class) annotation.

一旦你处理了这个基本工作单元的所有用例,你就提升了一个级别。在这里你做的完全相同,但你只处理来自当前级别下面的级别的异常。这可以使您的测试代码保持良好的结构,并允许您快速浏览架构以找出出错的地方,而不必遍布整个地方。

Once you have handled all your usecases for this basic unit of work, you move up a level. Here you do exactly the same, but you only handle the exceptions that come from the level right below the current one. This keeps your testing code well structured and allows you to quickly run through the architecture to find where things go wrong, instead of having to hop all over the place.

此时应该清楚我们将如何处理这些异常。有两种类型的输入:有效输入和错误输入(输入在严格意义上是有效的,但它不正确)。

At this point it should be clear how we're going to handle these exceptions. There are 2 types of input: valid input and faulty input (the input is valid in the strict sense, but it's not correct).

当您使用有效输入时,您正在设置隐含的期望值,即您编写的任何测试都将起作用。

When you work with valid input you're setting the implicit expectancy that whatever test you write, will work.

这样的方法调用如下所示: existingUserById_ShouldReturn_UserObject 。如果此方法失败(例如:抛出异常),那么您就知道出现了问题并且可以开始挖掘。

Such a method call can look like this: existingUserById_ShouldReturn_UserObject. If this method fails (e.g.: an exception is thrown) then you know something went wrong and you can start digging.

通过添加另一个测试( nonExistingUserById_ShouldThrow_IllegalArgumentException )使用错误的输入并期望一个异常,你可以看到你的方法是否做了它应该做错误的输入。

By adding another test (nonExistingUserById_ShouldThrow_IllegalArgumentException) that uses the faulty input and expects an exception you can see whether your method does what it is supposed to do with wrong input.

您试图在测试中做两件事:检查输入的有效和错误。通过将它分成两个方法,每个方法都做一件事,你将有更清晰的测试和更好的概述出错的地方。

You were trying to do two things in your test: check for valid and faulty input. By splitting this into two method that each do one thing, you will have much clearer tests and a much better overview of where things go wrong.

通过保持分层单位请记住,您还可以减少层次结构中较高层的所需测试数量,因为您不必考虑下层中可能出错的所有事物:当前层下面的层是虚拟保证你的依赖项工作,如果出现问题,它就在你当前的层中(假设较低的层本身不会抛出任何错误)。

By keeping the layered unit of works in mind you can also reduce the amount of tests you need for a layer that is higher in the hierarchy because you don't have to account for every thing that might have gone wrong in the lower layers: the layers below the current one are a virtual guarantee that your dependencies work and if something goes wrong, it's in your current layer (assuming the lower layers don't throw any errors themselves).

这篇关于如何测试没有抛出异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆