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 ...
随机推荐
- 【Linux计划】XSI IPC
三种IPC这就是所谓的XSI IPC,每间: 消息队列 信号量 共享存储器 以下分别介绍三种IPC的使用方法. 1.消息队列 消息队列是消息的链接表,具有例如以下函数接口: msgget:创建一个新队 ...
- Android Fragment——详细解释
1.Fragment概述 在一个Activity中. Fragment代表UI的一个部分或者一个行为.一个Activity能够结合多个Fragment对象,也能够在多个activity中使用同样Fra ...
- C/C++回调方式系列之一 函数指针和函数回调模式
一.函数指针 1. 函数的定义 return_type function_name(parameter list) { function_body } return_type: 返回值,函数一定有返回 ...
- XF 滑块和步进控件
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http:/ ...
- Win8 Metro(C#)数字图像处理--2.39二值图像投影
原文:Win8 Metro(C#)数字图像处理--2.39二值图像投影 [函数名称] 二值图像投影 ImageProjection(WriteableBitmap src) ...
- SqlServer 监控发布中未分发的命令数
原文:SqlServer 监控发布中未分发的命令数 对于查看未分发的命令数,我们通常这样查看. 然而当服务器有很多发布时,一个个打开查看就很麻烦 当然,如果想用脚本查看就更方便了,运行下面的语句 -- ...
- Android零基础入门第2节:Android 系统架构和应用组件那些事
原文:Android零基础入门第2节:Android 系统架构和应用组件那些事 继上一期浅谈了Android的前世今生,这一期一起来大致回顾一下Android 系统架构和应用组件. 一.Android ...
- Qt使Release版本可调试
只需在pro文件中加入 QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO QMAKE_LFLAGS_RELEASE = $$ ...
- Qt编程规范
一.概述 良好的编程规范可以大幅提高一个程序的可读性.可理解性和可维护性. 本规范参考Effective C++中文版.Google C++编码规范及Qt编码风格. 二.头文件 1) #de ...
- 线程天敌TerminateThread与SuspendThread
线程天敌TerminateThread与SuspendThread 作者:童磊(magictong) 目的:不是演示TerminateThread和SuspendThread的原理而是希望能在自己的程 ...