当前位置: 首页 > article >正文

基于JUnit4和JUnit5配合例子讲解JUnit的两种运行方式

1 引言

最近读的书有老有新,在读的过程中都完全完成了相应例子的构建和运行。在读《Spring in Action》1第4版时,其第37页的例子(以下称例子1)基于JUnit 4,并需要spring-test.jar;而在读《JUnit in Action》2第3版时,其第7页的例子(以下称例子2)基于JUnit 5,并采用自动化构建工具Maven运行。为此作为学习记录,本文将自己手工运行例子1和Maven运行例子2的过程记录下来,给出手工和Maven运行JUnit的两种方式,同时比较JUnit 4 和 JUnit 5的些许区别。

JUnit 是一个单元测试框架,由软件工程领域的大牛Erich Gamma和Kent Beck在1997年发布。JUnit能帮助我们构建自动化单元测试,是Java语言自动化测试的事实标准。它能简化编写自动化测试程序,尤其是当程序规模大且不断变动时,亦即当进行回归测试时,其作用会凸显。

JUnit 4大概在2010年左右广泛使用,书《JUnit in Action》的第2版是基于此版本的。JUnit 5大概在2020年左右逐渐广泛使用,《JUnit in Action》2第3版是基于此版本的。目前,在读一些稍微旧一点的书籍时,或者在参加一些项目的培训时,仍然会见到JUnit 4版本的使用。为此,本文例子1将基于JUnit 4讲解,而例子2将基于JUnit 5版本讲解。

例子1所依赖的环境为:

名称版本
JDK1.8.0_281
Spring4.1.1
JUnit4.11

例子2所依赖的环境为:

名称版本
JDK1.8.0_281
JUnit5.6.0
Maven3.8.8

2 例子

2.1 例子1

例子1本来在书中是利用Gradle工具构建的,我改成了手工运行,相应地文件夹结构也改成我自己的了。因为后续我还要运行该书中的很多例子,所以我把例子所依赖的jar都放到了一个固定的文件夹lib中,即D:\StudyCase\java\servletjsp\rbprj\springinaction\lib中。该例子是一个基于Spring的普通Java程序,并用xml配置文件形式写了测试程序,演示了Spring依赖注入的效果。

CompactDisc.java的内容如下:

package soundsystem;

// javac -d classes src/soundsystem/CompactDisc.java

public interface CompactDisc {
  void play();
}

SgtPeppers.java的内容如下:

package soundsystem;
import org.springframework.stereotype.Component;

// javac -classpath D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-core-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-beans-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-context-4.1.1.RELEASE.jar;classes;. -d classes src/soundsystem/SgtPeppers.java

@Component
public class SgtPeppers implements CompactDisc {

  private String title = "Sgt. Pepper's Lonely Hearts Club Band";  
  private String artist = "The Beatles";
  
  public void play() {
    System.out.println("Playing " + title + " by " + artist);
  }
  
}

采用自动配置方式的xml文件soundsystem.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:c="http://www.springframework.org/schema/c"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <context:component-scan base-package="soundsystem" />

</beans>

测试代码CDPlayerXMLConfigTest.java的内容如下:

package soundsystem;

// javac -classpath D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\system-rules-1.18.0.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\junit-4.11.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-test-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-core-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-beans-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-context-4.1.1.RELEASE.jar;classes;. -d classes src/soundsystem/CDPlayerXMLConfigTest.java

// java -classpath D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-aop-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\hamcrest-core-1.3.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\system-rules-1.18.0.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\junit-4.11.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-test-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-expression-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\commons-logging-1.1.3.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-core-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-beans-4.1.1.RELEASE.jar;D:\StudyCase\java\servletjsp\rbprj\springinaction\lib\spring-context-4.1.1.RELEASE.jar;classes;. org.junit.runner.JUnitCore soundsystem.CDPlayerXMLConfigTest

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
//import org.junit.contrib.java.lang.system.StandardOutputStreamLog;
import org.junit.contrib.java.lang.system.SystemOutRule;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:soundsystem.xml")
public class CDPlayerXMLConfigTest {

  @Rule
  public final SystemOutRule log = new SystemOutRule().enableLog();

  //@Autowired
  //private MediaPlayer player;

  @Autowired
  private CompactDisc cd;

  @Test
  public void cdShouldNotBeNull() {
    assertNotNull(cd);
  }
  
  //@Test
  /*public void play() {
    player.play();
    assertEquals(
        "Playing Sgt. Pepper's Lonely Hearts Club Band by The Beatles\n", 
        log.getLog());
  }*/

}

从上面代码和前述中可以看出:

  1. Spring 4要与JUnit 4配合使用。
  2. 在JUnit 4 版本下,org.junit.contrib.java.lang.system.StandardOutputStreamLog已经不存在,需改用org.junit.contrib.java.lang.system.SystemOutRule,相应地在lib文件夹中需加上system-rules-1.18.0.jar,该jar的版本可微调。可见,虽然该书是2015年出版,JUnit 4也相对比较老了,但代码还是更老。
  3. 在JUnit 4 下,已经开始使用标注(Annotation)Test,且测试类不用继承JUnit 框架中的特定类。
  4. 由于是测试的基于Spring 4 的程序,需要包含spring-test-4.1.1.RELEASE.jar。

该例子经过编译后,即可运行,编译或运行指令已写在上面代码中。运行结果如下:
在这里插入图片描述
阅读上面的运行结果,可以看出运行成功,测试通过。虽然出现了3个 Could not instantiate TestExecutionListener,但是这3个TestExecutionListener与本程序无关。最关键的是

信息: Using TestExecutionListeners: [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@ba4d54, org.springframework.test.context.support.DirtiesContextTestExecutionListener@12bc6874]

表明使用的是依赖注入TestExecutionListener,本例子正是测试依赖注入的。

手工不能直接运行该测试类,需要将测试类作为org.junit.runner.JUnitCore的参数运行,该类作为命令行的参数需用包的形式书写,即soundsystem.CDPlayerXMLConfigTest

2.2 例子2

该例子是一个非常简单的基于JUnit 5的例子。因为使用Maven运行,其文件夹结构需符合Maven的要求,如下:

├── src/
│   ├── main/
│   │	├──java/
│   │	│   ├──/com/manning/junitbook/ch01/Calculator.java
│   └── test/
│   │	├──java/
│   │	│   ├──/com/manning/junitbook/ch01/CalculatorTest.java
├── pom.xml

Calculator.java的内容如下:

package com.manning.junitbook.ch01;

public class Calculator {
    public double add(double number1, double number2) {
        return number1 + number2;
    }
}

CalculatorTest.java的内容如下:

package com.manning.junitbook.ch01;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class CalculatorTest {

    @Test
    public void testAdd() {
        Calculator calculator = new Calculator();
        double result = calculator.add(10, 50);
        assertEquals(60, result, 0);
    }
}

pom.xml的内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.manning.junitbook</groupId>
    <artifactId>ch01-jumpstart</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>ch01-jumpstart</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.6.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.6.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.6.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

在命令行中输入mvn clean install,会出现如下运行结果:
在这里插入图片描述
证明测试成功,并通过。同时会在根路径,即包含pom.xml的路径,产生target文件夹,其中内容包含可执行的class文件。使用Maven自动化构建工具是很方便的。

3 总结

本文基于不同的JUnit版本(4和5)分别介绍了JUnit的两种不同使用方式—手工和Maven,通过代码的方式可以看出JUnit 5的包结构发生了改变,能帮助初学者入门JUnit 框架的使用和代码阅读。若想对JUnit 更深入了解,推荐阅读文献2


  1. Craig Walls. Spring in Action. 4th Edition. Shelter Island, NY: Manning Publications, 2015, pp37-37. ↩︎

  2. CĂTĂLIN TUDOSE. JUnit in Action. 3rd Edition. Shelter Island, NY: Manning Publications, 2020, pp7-12. ↩︎ ↩︎ ↩︎


http://www.kler.cn/a/537093.html

相关文章:

  • Java/Kotlin双语革命性ORM框架Jimmer(一)——介绍与简单使用
  • 摄像头模块烟火检测
  • c++计算机教程
  • 攻防世界 文件上传
  • c++ 浮点数比较判断
  • 【Leetcode 每日一题】47. 全排列 II
  • 笔记本电脑屏幕泛白问题解决详解(AMD显卡)
  • .NET 8 WebAPI文件下载包含断点续传和取消下载
  • STM32 CUBE Can调试
  • (11)gdb 笔记(4):设置执行方向 set exec-direction,
  • OpenCV:图像修复
  • RabbitMQ 从入门到精通:从工作模式到集群部署实战(四)
  • CSS 伪类(Pseudo-classes)的详细介绍
  • Java基础学习笔记-封装
  • Python在数据科学中的高效应用:从数据处理到模型部署的实战指南
  • 高效运维!K8s 多节点自动安全排空
  • 为多个GitHub账户配置SSH密钥
  • PostgreSQL 中的 EXTRACT 函数_操作日期
  • 服务器磁盘高占用排查
  • Qt 数据库SQLite 使用【01】基本功能
  • Lua中文语言编程源码-第十一节,其它小改动汉化过程
  • Android studio 创建aar包给Unity使用
  • 使用 Axios ——个人信息修改
  • ES6 Set 数据结构用法总结
  • Flutter List 的 every 如果回调函数抛出异常 应该如何处理
  • 尚硅谷 vue3+TS 课程笔记