Junit4学习使用和总结
Junit4学习使用和总结
部分资料来源于网络
编辑于:20190710
一、Junit注解理解
1、@RunWith 首先要分清几个概念:测试方法、测试类、测试集、测试运行器。其中测试方法就是用@Test注解的一些函数。测试类是包含一个或多个测试方法的一个**Test.java文件,测试集是一个suite,可能包含多个测试类。测试运行器则决定了用什么方式偏好去运行这些测试集/类/方法。当类被@RunWith注解修饰(放在测试类上使用),或者类继承了一个被该注解修饰的类,JUnit将会使用这个注解所指明的运行器(runner)来运行测试,而不使用JUnit默认的运行器。
2、@Before 当编写测试方法时,经常会发现一些方法在执行前需要创建(初始化)相同的对象,使用@Before注解一个public void 方法会使该方法在@Test注解方法被执行前执行,就可以为@Test注解方法初始化对象数据,注:父类的@Before注解方法会在子类的@Before注解方法执行前执行。
3、@After 如果在@Before注解方法中分配了额外的资源,那么在测试执行完后,需要释放分配的资源。使用@After注解一个public void方法,该方法会在@Test注解方法执行后被执行。即使在@Before注解方法、和@Test注解方法中抛出了异常,所有的@After注解方法依然会被执行。注:父类中的@After注解方法会在子类@After注解方法执行后被执行
public class MathTest { @Before
public void setUp() throws Exception {
throw new Exception();
} @Test
public void testAdd() {
/*
* Junit中assertTrue(String message,boolean condition)的使用
* condition为true则运行成功,condition为false则运行失败并打印出message信息。
* 断言:assert 断言assert的好多方法可以直接使用,主要是使用了静态导入:import static org.junit.Assert.*;
*/
assertTrue("如果不相等展示这条语句", Math.addExact(1, 1) == 3);
} @After
public void tearDown() throws Exception {
System.out.println("after");
}
}
测试结果:
4、@BeforeClass 一些测试需要共享代价高昂的步骤(如数据库登录),这会破坏测试独立性,通常是需要优化的,使用@BeforeClass注解一个public static void 方法,并且该方法不带任何参数,会使该方法在所有测试方法被执行前执行一次,并且只执行一次。注:父类的@BeforeClass注解方法会在子类的@BeforeClass注解方法执行前执行
5、@AfterClass 如果在@BeforeClass注解方法中分配了代价高昂的额外的资源,那么在测试类中的所有测试方法执行完后,需要释放分配的资源。使用@AfterClass注解一个public static void方法会使该方法在测试类中的所有测试方法执行完后被执行,即使在@BeforeClass注解方法中抛出了异常,所有的@AfterClass注解方法依然会被执行。注:父类中的@AfterClass注解方法会在子类@AfterClass注解方法执行后被执行。
关于@BeforeClass、@AfterClass、@Before 和 @After 总结和对比:
(1)@BeforeClass 和 @AfterClass 只会在类中被执行一次,对于那些比较“昂贵”的资源的分配或者释放来说是很有效的。相比之下对于那些需要在每次运行之前都要初始化或者在运行之后都需要被清理的资源来说使用@Before和@After同样是一个比较明智的选择。
(2)@Before 和 @After 会在每次运行前后都要执行,如果每次运行前后都需要清理资源的话,@Before和@After是一个比较明智的选择。其中@BeforeClass 和 @AfterClass必须声明为public static,而@Before和@After必须声明为public 并且非static。
6、@Ignore 对包含测试类的类或@Test注解方法使用@Ignore注解将使被注解的类或方法不会被当做测试执行(即不测试被@Ignore注解的类或方法)。JUnit执行结果中会报告被忽略的测试数。
7、@Test @Test注解的public void方法(并且不带任何参数)将会被当做测试用例。JUnit每次都会创建一个新的测试实例,然后调用@Test注解方法,任何异常的抛出都会认为测试失败。
@Test注解提供2个参数:
(1)“expected” 定义测试方法应该抛出的异常,如果测试方法没有抛出异常或者抛出了一个不同的异常,则 JUnit 会认为这个测试没有通过。这为验证被测试方法在错误的情况下是否会抛出预定的异常提供了便利。举例来说,方法 supportDBChecker 用于检查用户使用的数据库版本是否在系统的支持的范围之内,如果用户使用了不被支持的数据库版本,则会抛出运行时异常 UnsupportedDBVersionException。
(2)“timeout” 指定被测试方法被允许运行的最长时间应该是多少,如果测试方法运行时间超过了指定的毫秒数,则JUnit认为测试失败。这个参数对于性能测试有一定的帮助。例如,如果解析一份自定义的 XML 文档花费了多于 1 秒的时间,就需要重新考虑 XML 结构的设计。
public class ExpectedTest { @Test(expected = Exception.class)
public void testAdd() throws Exception {
throw new Exception();
} }
测试结果:
public class TimeoutTest { @Test(timeout = 5000)
public void testAdd() {
for (; ; ) {}
} }
测试结果:
8、@Parameters 用于使用参数化功能。
下面是综合上面几个常用的注解的测试方法
public class LinkinTest { @BeforeClass
public static void init() {
System.out.println("*****这里是类级别的初始化方法*****");
} @AfterClass
public static void destroy() {
System.out.println("*****这里是类级别的销毁方法*****");
} @Before
public void setUp() {
System.out.println("==这里是方法级别的初始化方法==");
} @After
public void tearDown() {
System.out.println("==这里是方法级别的销毁方法==");
} @Test
public void testLinkin1() {
assertTrue(true);
System.out.println("《这里是普通测试方法一》");
} @Test
public void testLinkin2() {
assertTrue(true);
System.out.println("《这里是普通测试方法二》");
} @Test(expected = NullPointerException.class)
public void testLinkin3() {
System.out.println("《这里是异常的测试方法》");
String linkin = null;
System.out.println(linkin.toString());
} @Test(timeout = 1000)
public void testLinkin4() {
try {
Thread.sleep(2);
} catch (Exception e) {
e.printStackTrace();
//Assert 断言中的方法fail(String message)
fail("时间测试不通过。。。");
} finally {
System.out.println("《这里是测试代码运行时间》");
}
} }
运行结果:
二、Parameterized参数化和自动注解一起使用
JUnit参数化测试的五个步骤:
(1)为准备使用参数化测试的测试类指定特殊的运行器 org.junit.runners.Parameterized。
(2)为测试类声明几个变量,分别用于存放期望值和测试所用数据。
(3)为测试类声明一个带有参数的公共构造函数,并在其中为第二个环节中声明的几个变量赋值。
(4)为测试类声明一个使用注解 org.junit.runners.Parameterized.Parameters 修饰的,返回值为 java.util.Collection 的公共静态方法,并在此方法中初始化所有需要测试的参数对。
(5)编写测试方法,使用定义的变量作为参数进行测试。
下面通过Junit测试几种jar包数据拷贝的性能:
@FunctionalInterface
public interface PropertiesCopier {
void copyProperties(Object source, Object target) throws Exception;
} // 全局静态 BeanCopier,避免每次都生成新的对象
class StaticCglibBeanCopierPropertiesCopier implements PropertiesCopier {
private static BeanCopier copier = BeanCopier.create(String.class, String.class, false); @Override
public void copyProperties(Object source, Object target) throws Exception {
copier.copy(source, target, null);
}
} /**
* 使用cglib方法实现bean的拷贝
*/
class CglibBeanCopierPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties(Object source, Object target) throws Exception {
BeanCopier copier = BeanCopier.create(source.getClass(), target.getClass(), false);
copier.copy(source, target, null);
}
} /**
* 使用spring实现bean的拷贝
*/
class SpringBeanUtilsPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties
(Object source, Object target) throws Exception {
org.springframework.beans.BeanUtils.copyProperties(source, target);
}
} /**
* 使用Apache实现bean的拷贝
*/
class CommonsPropertyUtilsPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties(Object source, Object target) throws Exception {
org.apache.commons.beanutils.PropertyUtils.copyProperties(target, source);
}
} class CommonsBeanUtilsPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties
(Object source, Object target) throws Exception {
org.apache.commons.beanutils.BeanUtils.copyProperties(target, source);
}
}
/**
* 使用参数化运行器进行执行
*/
@RunWith(Parameterized.class)
public class PropertiesCopierTest { @Parameterized.Parameter(0)
public PropertiesCopier propertiesCopier; // 测试次数
private static List<Integer> testTimes = Arrays.asList(100, 1000, 10_000, 100_000, 1_000_000); // 测试结果以表格的形式输出
private static StringBuilder resultBuilder = new StringBuilder("| 实现方法| 100| 1,000| 10,000| 100,000| 1,000,000|\n").
append("|------------|------------|------------|------------|------------|------------|\n"); /*
* 初始化需要使用的参数
*/
@Parameterized.Parameters
public static Collection<Object[]> data() {
Collection<Object[]> params = new ArrayList<>();
params.add(new Object[]{new StaticCglibBeanCopierPropertiesCopier()});
params.add(new Object[]{new CglibBeanCopierPropertiesCopier()});
params.add(new Object[]{new SpringBeanUtilsPropertiesCopier()});
params.add(new Object[]{new CommonsPropertyUtilsPropertiesCopier()});
params.add(new Object[]{new CommonsBeanUtilsPropertiesCopier()});
return params;
} /*
* 每一次运行前的初始化处理
*/
@Before
public void setUp() throws Exception {
String name = propertiesCopier.getClass().getSimpleName().replace("PropertiesCopier", "");
resultBuilder.append("|").append(name).
append("|");
} @Test
public void copyProperties() throws Exception {
String source = "小红";
String target = new String();
propertiesCopier.copyProperties(source, target);
// 按照数组中的次数进行拷贝次数执行
for (Integer time : testTimes) {
long start = System.nanoTime();
for (int i = 0; i < time; i++) {
propertiesCopier.copyProperties(source, target);
}
// 每完成规定次数的拷贝,算出当前规定次数拷贝的用时多少毫秒,并且加入resultBuilder尾部
// 注nanoTime():1纳秒=0.000001 毫秒 1纳秒=0.000000001秒
resultBuilder.append((System.nanoTime() - start) / 1_000_000D).append("|");
}
resultBuilder.append("\n");
} @AfterClass
public static void tearDown() throws Exception {
System.out.println("测试结果:");
System.out.println(resultBuilder);
}
}
测试结果:
从测试结果来看:结果表明,Cglib 的 BeanCopier 的拷贝速度是最快的,全局静态 BeanCopier即使是百万次的拷贝也只需要 4 毫秒! 相比而言,最差的是 Commons 包的 BeanUtils.copyProperties 方法,100 次拷贝测试与表现最好的 Cglib 相差 200 倍之多。百万次拷贝更是出现了 2400 倍的性能差异!
Junit4学习使用和总结的更多相关文章
- Junit4学习(一)新建Junit4工程
一,学习Junit4,学以致用 二,熟悉编写流程 工具:Eclipse,Junit包,hamcrest.core包 1,打开Eclipse开发工具,新建工程:file->Java Project ...
- Junit4学习笔记
一.初始化标注 在老Junit4提供了setUp()和tearDown(),在每个测试函数调用之前/后都会调用. @Before: Method annotated with @Before exec ...
- Junit4学习(六)Junit4参数化设置
一,背景, 有时候会对相同的代码结构做同样的操作,不同的时对参数的设置数据和预期结果:有没有好的办法提取出来相同的代码,提高代码的可重用度,junit4中使用参数化设置,来处理此种场景: 二,代码展示 ...
- JUnit4学习
参考:http://www.cnblogs.com/yangxia-test/p/3996120.html JUnit4是一个开源的java单元测试框架,我们只需要引入一个包,就可以使用它的功能 先说 ...
- JUnit4 学习笔记
一.环境搭建: 1.需要用的包: JUnit4.7:http://files.cnblogs.com/files/ShawnYang/junit4.7.zip hamcrest-1.2:http:// ...
- junit4学习(Annotation)
在一个测试类中,所有被@Test注解修饰的public,void方法都是testcase,可以被JUNIT执行. @Retention(value=RUNTIME) @Target(value=MET ...
- Junit4学习笔记--方法的执行顺序
package com.lt.Demo.TestDemo; import java.util.Arrays; import java.util.Collection; import org.junit ...
- Junit4学习(五)Junit4测试套件
一,背景 1,随着开发规模的深入和扩大,项目或越来越大,相应的我们的测试类也会越来越多:那么就带来一个问题,假如测试类很多,就需要多次运行,造成测试的成本增加:此时就可以使用junit批量运行测试类的 ...
- Junit4学习(四)Junit4常用注解
一,背景知识: 由前面的知识可以知道: /* * @Test:将一个普通方法修饰为一个测试方法 * @Test(exception=XXX.class) * @Test ...
随机推荐
- HDOJ 2189 悼念512四川汶川大地震遇难者——来生一起走 【生成函数】
意甲冠军:没有解释的很清楚. 策略:如果, 这是改变一个简单的生成函数. 这道题做了好久,才明确是那有毛病.还是理解的不够深刻. AC代码: #include<stdio.h> #incl ...
- [GEiv]第七章:着色器 高效GPU渲染方案
第七章:着色器 高效GPU渲染方案 本章介绍着色器的基本知识以及Geiv下对其提供的支持接口.并以"渐变高斯模糊"为线索进行实例的演示解说. [背景信息] [计算机中央处理器的局限 ...
- XF 定制图片
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- WPF数据模板的数据触发器的使用
<Window x:Class="CollectionBinding.MainWindow" xmlns="http://schemas.micros ...
- .Net 开源服务 and Net站点
小泥鳅博客系统也是一个.NET平台的开源免费博客系统,创建于2008年夏天,基于.Net平台开发,拥有完整的文章发布,评论,订阅,标签等功能,满足个人/团队信息发布需求,可作为Blog,CMS,甚至建 ...
- WPF 为资源字典 添加事件响应的后台类
原文:WPF 为资源字典 添加事件响应的后台类 前言,有许多同学在写WPF程序时在资源字典里加入了其它控件,但又想写事件来控制这个控件,但是资源字典没有CS文件,不像窗体XAML还有一个后台的CS文件 ...
- GIS基础软件及操作(四)
原文 GIS基础软件及操作(四) 练习四.空间数据处理 1.空间数据处理(融合.合并.剪切.交叉.合并)2.设置地图投影及投影变换 空间数据处理 数据:云南县界.shp; Clip.shp西双版纳森林 ...
- 微信小程序把玩(一)Hello WeApp
原文:微信小程序把玩(一)Hello WeApp 本篇默认已经成功安装微信小程序工具 新建项目 AppID查看公众开发平台设置查看(https://mp.weixin.qq.com) 项目名称随意填写 ...
- RedHat 7.3 修改ASM磁盘绑定路径
RedHat 7中,很多命令发生了改变,绑定磁盘不再是start_udev,而是udevadm,具体绑定方式,请看另一篇博文: http://www.cnblogs.com/zx3212/p/6757 ...
- win10不用密码直接登陆设置
点击开始菜单里的[运行],然后输入control userpasswords2 或者 netplwiz ,然后点击确定,如下图所示. 点击后,在用户帐户对话框里可以看到“要使用本计算机,用户必须输入用 ...