今天做单元测试,要求做下路径覆盖,于是乎要对异常进行测试了。这个第一次搞,
不知道怎么下手,当遇到异常,马上终止测试(测试没有通过),但是不在catch中写的话,有不符合要求,于是网上转了下。算是解决了。
测试是否抛出正确的异常(Test throwing the right exception)
博客分类:
问题:
你是否想过异常也要去测试?你想了怎么验证一个方法是否在某种特定的情况下抛出期望的异常,也许你正在找是否要测试,以及有没有简单的测试方法
背景:
要想知道任何实现这种测试,你需要了解JUnit如何判定一个测试时通过还是失败。如果一个断言失败或者抛出一个异常的时候,测试就会失败,否则测试就通过。换句话说,如果一个测试全部走完,就是说程序从头运行到了尾,而没有从中间跳过,那么它就通过了。知道了这些,就足够你推断出然后写这种测试了:如果该抛出异常的代码段没有抛出异常,那么这个测试就应该失败;测试只能捕捉期望的异常;任何其他的异常都应该由JUnit框架捕捉。
诀窍:
下面的代码展示了,如何写这种验证是否抛出正确异常的测试示例:
首先分析上面的代码
1. 找到可能抛出异常的代码段,将它放入一个try语句内。
2. 调用了应该抛出异常的方法以后,在try语句内写一个fail()方法来说明:“如果运行到了这里,那么说明期望的异常没有被抛出”。
3. 添加一个catch语句以捕获期望的异常。
4. 在catch语句内,如果需要的话,验证捕获的异常的属性与你期望的相同。
5. 声明该测试方法会抛出异常,这可以让代码适应性更强。有人可能会在测试程序外声明这个方法可抛出其他的异常,这种变化不应该影响你的测试,因此它不应该导致你的测试不能被编译。
讨论:
如果测试的方法抛出其他的异常---------不同于你要捕获的异常-----那么JUnit将报告一个error,而不是failure,因为测试方法将一个异常抛出给JUnit框架。记住这样的error一般是环境或者测试程序自身的错误,而不是产品代码的问题。如果产品代码抛出了一个预期之外的异常,那么一般可能是潜在的问题阻碍了测试的正常运行。
一个更面向对象的解决办法
先看一个匿名内部类
虽然有人觉得Java的匿名内部类不太好读,但这个方法的意图再明显不过了:"测试这段代码是否抛出期望的异常"。可以按如下的方式实现assertThrows()方法:
我们捕捉了所有的异常,而不仅是期望的异常,这是因为当编译的时候,我们还不知道代码会抛出什么样的异常。如果这样设置断言,那么错误信息就很重要,因为你取走了错误信息的控制权。另外一个可选的方案是,在assertThrows()方法中添加另外一个参数,用来接收自定义的异常,最后,因为我们必须测试所有的异常,我们必须将捕获的异常是否是期望的异常的实例,这与使用instanceof()方法是一样的。
注意写的断言:
如果你的断言与特定的异常相关,那么你要小心:如果验证异常对象的结构过于紧凑,那么可能导致测试与产品代码耦合得过强。这时候,测试的结果可能有点不太可靠。假设异常信息是给终端用户看,而你要写直接验证该消息的断言。一般来说,你会照着如下的方式编写测试代码:
测试代码看上去很清楚:如果一个用户不输入用户名的情况下登录,那么登录模块就抛出一个MissingEntryException。这个异常包含了登录所缺少的必要项的名称,以及提供给终端用户的信息。这看起来很好,因为这个异常对象包含的信息非常简单,它包含的数据像终端用户读取的信息一样易于理解。虽然catch语句中的第一断言写得不错,但是第二个有点不同的意见,虽然userName是程序的内部名称,并且是行为的一部分,但给终端用户看的信息可以在不影响登录功能的前提下随时改变。换句话说,如果userName改变的话,测试程序就需要随之改变。然而,测试似乎不应该随着终端用户信息的改变而改变,由于测试时现在写的,将来任何属性值的改变,都会要求测试程序随之改变。
这个例子中,我们建议去除第二个断言而仅保留第一个,因为涉及的一般准则是:将给终端用户看的信息与内部对象的行为相分离。你可以经常简单地初始化应该异常对象,然后检查它的toString()以及getMessage()方法的返回值。
你是否想过异常也要去测试?你想了怎么验证一个方法是否在某种特定的情况下抛出期望的异常,也许你正在找是否要测试,以及有没有简单的测试方法
背景:
要想知道任何实现这种测试,你需要了解JUnit如何判定一个测试时通过还是失败。如果一个断言失败或者抛出一个异常的时候,测试就会失败,否则测试就通过。换句话说,如果一个测试全部走完,就是说程序从头运行到了尾,而没有从中间跳过,那么它就通过了。知道了这些,就足够你推断出然后写这种测试了:如果该抛出异常的代码段没有抛出异常,那么这个测试就应该失败;测试只能捕捉期望的异常;任何其他的异常都应该由JUnit框架捕捉。
诀窍:
下面的代码展示了,如何写这种验证是否抛出正确异常的测试示例:
- public void testConstructorDiesWithNull() throws Exception{
- try{
- Fraction oneOverZero = new Fraction(1,0);
- fail("Created fraction 1/0! That's undefined!");
- }
- catch(IllegalArgumentException excepted){
- assertEquals("denominator",excepted.getMessage());
- }
- }
首先分析上面的代码
1. 找到可能抛出异常的代码段,将它放入一个try语句内。
2. 调用了应该抛出异常的方法以后,在try语句内写一个fail()方法来说明:“如果运行到了这里,那么说明期望的异常没有被抛出”。
3. 添加一个catch语句以捕获期望的异常。
4. 在catch语句内,如果需要的话,验证捕获的异常的属性与你期望的相同。
5. 声明该测试方法会抛出异常,这可以让代码适应性更强。有人可能会在测试程序外声明这个方法可抛出其他的异常,这种变化不应该影响你的测试,因此它不应该导致你的测试不能被编译。
讨论:
如果测试的方法抛出其他的异常---------不同于你要捕获的异常-----那么JUnit将报告一个error,而不是failure,因为测试方法将一个异常抛出给JUnit框架。记住这样的error一般是环境或者测试程序自身的错误,而不是产品代码的问题。如果产品代码抛出了一个预期之外的异常,那么一般可能是潜在的问题阻碍了测试的正常运行。
一个更面向对象的解决办法
先看一个匿名内部类
- public void testForException(){
- assertThrows(MyException.class, new ExceptionClosure(){
- public Object execute(Object input) throws Exception{
- return doSomethingThatShouldThrowMyException();
- }
- });
- }
虽然有人觉得Java的匿名内部类不太好读,但这个方法的意图再明显不过了:"测试这段代码是否抛出期望的异常"。可以按如下的方式实现assertThrows()方法:
- public static void assertThrows(Class expectedExceptionClass, ExceptionalClosure closure){
- String expectedExceptionClassName = expectedExceptionClass.getName();
- try{
- closure.execute(null);
- fail("Block did not throw an exception of type"+expectedExceptionClassName);
- }
- catch(Exception e){
- assertTrue("Caught exception of type <" + e.getClass().getName()
- +">, expected one of type <"
- +expectedExceptionClassName+">",
- expectedExceptionClass.isInstance(e));
- }
- }
我们捕捉了所有的异常,而不仅是期望的异常,这是因为当编译的时候,我们还不知道代码会抛出什么样的异常。如果这样设置断言,那么错误信息就很重要,因为你取走了错误信息的控制权。另外一个可选的方案是,在assertThrows()方法中添加另外一个参数,用来接收自定义的异常,最后,因为我们必须测试所有的异常,我们必须将捕获的异常是否是期望的异常的实例,这与使用instanceof()方法是一样的。
注意写的断言:
如果你的断言与特定的异常相关,那么你要小心:如果验证异常对象的结构过于紧凑,那么可能导致测试与产品代码耦合得过强。这时候,测试的结果可能有点不太可靠。假设异常信息是给终端用户看,而你要写直接验证该消息的断言。一般来说,你会照着如下的方式编写测试代码:
- public void testNameNoEntered(){
- try{
- log("", "password");
- fail("User logged in without a user name !");
- }
- atch(MissingEntryException expected){
- assertEquals("userName", expected.getEnteryName());
- assertEquals("Please enter a user name and try again",
- expected.getMessage());
- }
- }
测试代码看上去很清楚:如果一个用户不输入用户名的情况下登录,那么登录模块就抛出一个MissingEntryException。这个异常包含了登录所缺少的必要项的名称,以及提供给终端用户的信息。这看起来很好,因为这个异常对象包含的信息非常简单,它包含的数据像终端用户读取的信息一样易于理解。虽然catch语句中的第一断言写得不错,但是第二个有点不同的意见,虽然userName是程序的内部名称,并且是行为的一部分,但给终端用户看的信息可以在不影响登录功能的前提下随时改变。换句话说,如果userName改变的话,测试程序就需要随之改变。然而,测试似乎不应该随着终端用户信息的改变而改变,由于测试时现在写的,将来任何属性值的改变,都会要求测试程序随之改变。
这个例子中,我们建议去除第二个断言而仅保留第一个,因为涉及的一般准则是:将给终端用户看的信息与内部对象的行为相分离。你可以经常简单地初始化应该异常对象,然后检查它的toString()以及getMessage()方法的返回值。
相关推荐
3. **异常处理**:测试异常处理逻辑,确保在出现错误时程序行为符合预期。 4. **正向测试**:验证正常输入和操作的正确性。 5. **负向测试**:验证程序对错误输入和非法操作的响应。 **自动饮料机案例** 在这个...
例如,文件可能会讲解如何设置一个基本的JUnit测试类,通常这个类会继承自`junit.framework.TestCase`(对于较旧的JUnit版本)或者使用注解`@RunWith(JUnit4.class)`(对于JUnit 4及以上版本)。 测试类中的每个...
JUnit测试jar包通常包含了JUnit框架的核心库和其他可能的扩展或辅助库,使得开发人员可以在他们的项目中引入这些测试工具。这个压缩包很可能包含了JUnit的不同版本,例如JUnit4或JUnit5,以及可能的依赖如Hamcrest...
5. **异常测试**:JUnit3允许你测试一个方法是否抛出了预期的异常,例如`try { ... } catch (Exception e) { fail("异常未正确抛出"); }` 6. **测试运行器**:JUnit3默认的运行器会顺序执行所有的测试,如果有测试...
《Junit测试学习文档》 在软件开发过程中,单元测试是一项至关重要的工作,它能确保代码的正确性,提高代码质量,并为后续的维护和重构提供保障。Junit作为Java编程语言中最流行的单元测试框架,是每个Java开发者...
本压缩包文件"javaweb中.java文件测试需要的框架(junit测试).rar"显然是为了帮助开发者理解如何在Java Web项目中使用JUnit进行测试。 **JUnit框架详解** JUnit是一个基于注解的测试框架,它的核心功能包括: 1....
在这个“junit测试案例程序”中,我们可以找到一些基本的JUnit测试用例示例,这对于初学者来说是极好的学习资源。 首先,JUnit的核心概念是测试类和测试方法。一个测试类通常对应于被测试的业务逻辑类,而测试方法...
下面将详细阐述JUnit测试的相关知识点。 1. **JUnit简介**: JUnit是由Ernst von Reiss和Kent Beck开发的一个开源项目,它是XUnit测试框架家族的一员,专为Java设计。JUnit提供了注解、断言、测试套件、定时器等...
`@Expected`注解可以指定测试方法预期抛出的异常类型,如果方法没有抛出预期的异常或者抛出了不同类型的异常,测试就会失败。 JUnit还支持断言(Assertions),这是测试的核心部分。通过使用如`assertEquals`、`...
在这个名为"junit测试小demo"的压缩包文件中,我们可以预期它包含了一些关于如何使用Junit进行单元测试的示例代码或教程。 首先,让我们来理解一下Junit的基本概念。Junit是一个开源项目,由Eclipse基金会维护,...
3. **异常测试**:`@Test(expected = Exception.class)`可以用来测试方法是否抛出了预期的异常。 4. **测试套件(Test Suites)**:`@Suite`注解允许将多个测试类组合成一个测试套件,便于一起运行。 5. **参数化...
创建JUnit测试类是单元测试的第一步。在Eclipse中,右键点击项目,选择"New" > "JUnit Test Case"。在此过程中,需要选择要测试的源代码类以及要测试的方法。测试类通常会继承自`org.junit.Test`注解的基类,并且每...
在实际使用中,开发人员通常会结合构建工具如Maven或Gradle,以及IDE如Eclipse、IntelliJ IDEA来运行JUnit测试。这些工具能够自动化测试执行,生成测试报告,帮助分析和调试。 总的来说,JUnit 4.7作为Java单元测试...
本文将详细介绍JUnit测试工具及其安装方法。 **一、JUnit简介** JUnit是一个开源的、基于Java的测试框架,主要用于编写和运行可重复的单元测试。它的设计理念是使测试成为开发过程中的一个自然部分,通过自动化测试...
这篇博文“生成junit测试类”可能讲述了如何使用特定工具或方法来自动化创建JUnit测试类的过程。下面将详细讨论JUnit测试、EasyMock和PowerMock等相关知识点。 1. JUnit测试:JUnit是Java编程语言的一个开源测试...
异常测试也是JUnit4的一个重要特性,可以使用`assertThrows()`来断言预期的异常是否被抛出。例如,`assertThatThrownBy(() -> someCode()).isInstanceOf(ExpectedException.class)`。 JUnit4还引入了`Assume`类,...
本资源"JUnit_Test_Code.zip"包含了一份关于如何使用JUnit进行测试的实例,以及图文并茂的讲解,对于理解和实践JUnit测试脚本非常有帮助。 在Java开发中,单元测试是对软件中的最小可测试单元进行检查和验证的过程...
这个“junit测试.zip”文件包含了JUnit库的jar包,它用于帮助进行程序的单元测试。单元测试是对软件中的最小可测试单元进行检查和验证,通常是一个方法或一个类。 在Java开发中,单元测试是质量保证的关键步骤,...
需要注意的是,测试应该覆盖所有可能的边界条件和异常情况,例如除数为零时的除法操作。 在Junit中,还有其他一些注解可以帮助我们进行更复杂的测试,比如`@Before`和`@After`,它们分别表示在每个测试方法之前和...