JUnit5 学习之一:基本操作,菜鸟教程 java 在线编辑器下载
SpringBoot:2.3.4.RELEASE
JUnit Jupiter:5.6.2
接下来开始实战,咱们先建好 SpringBoot 项目;
关于 lombok
为了简化代码,项目中使用了 lombok,请您在 IDEA 中安装 lombok 插件;
源码下载
如果您不想编码,可以在 GitHub 下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
| 名称 | 链接 | 备注 |
| :-- | :-- | :-- |
| 项目主页 | https://github.com/zq2599/blog_demos | 该项目在 GitHub 上的主页 |
| git 仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https 协议 |
| git 仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh 协议 |
这个 git 项目中有多个文件夹,本章的应用在 junitpractice 文件夹下,如下图红框所示:
junitpractice 是父子结构的工程,本篇的代码在 junit5experience 子工程中,如下图:
创建 Maven 父工程
为了便于管理整个系列的源码,在此建立名为 junitpractice 的 maven 工程,后续所有实战的源码都作为 junitpractice 的子工程;
junitpractice 的 pom.xml 如下,可见是以 SpringBoot 的 2.3.4.RELEASE 版本作为其父工程:
<?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>
<modules>
<module>simplebean</module>
<!--
<module>testenvironment</module>
-->
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>junitpractice</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
本篇的源码工程
接下来咱们准备一个简单的 SpringBoot 工程用于做单元测试,该工程有 service 和 controller 层,包含一些简单的接口和类;
创建名为 junit5experience 的子工程,pom.xml 如下,注意单元测试要依赖 spring-boot-starter-test:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>junitpractice</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<
groupId>com.bolingcavalry</groupId>
<artifactId>junit5experience</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>junit5experience</name>
<description>Demo project for simplebean in Spring Boot junit5</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
写一些最简单的业务代码,首先是 service 层的接口 HelloService.java:
package com.bolingcavalry.junit5experience.service;
public interface HelloService {
String hello(String name);
int increase(int value);
/**
该方法会等待 1 秒后返回 true,这是在模拟一个耗时的远程调用
@return
*/
boolean remoteRequest();
}
上述接口对应的实现类如下,hello 和 increase 方法分别返回 String 型和 int 型,remoteRequest 故意 sleep 了 1 秒钟,用来测试 Timeout 注解的效果:
package com.bolingcavalry.junit5experience.service.impl;
import com.bolingcavalry.junit5experience.service.HelloService;
import org.springframework.stereotype.Service;
@Service()
public class HelloServiceImpl implements HelloService {
@Override
public String hello(String name) {
return "Hello " + name;
}
@Override
public int increase(int value) {
return value + 1;
}
@Override
public boolean remoteRequest() {
try {
Thread.sleep(1000);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
return true;
}
}
添加一个简单的 controller:
package com.bolingcavalry.junit5experience.controller;
import com.bolingcavalry.junit5experience.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
private HelloService helloService;
@RequestMapping(value = "/{name}", method = RequestMethod.GET)
public String hello(@PathVariable String name){
return helloService.hello(name);
}
}
启动类:
package com.bolingcavalry.junit5experience;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Junit5ExperienceApplication {
public static void main(String[] args) {
SpringApplication.run(Junit5ExperienceApplication.class, args);
}
}
以上就是一个典型的 web 工程,接下来一起为该工程编写单元测试用例;
编写测试代码
在下图红框位置新增单元测试类:
测试类的内容如下,涵盖了刚才提到的常用注解,请注意每个方法的注释说明:
package com.bolingcavalry.junit5experience.service.impl;
import com.bolingcavalry.junit5experience.service.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
@Slf4j
class HelloServiceImplTest {
private static final String NAME = "Tom";
@Autowired
HelloService helloService;
/**
在所有测试方法执行前被执行
*/
@BeforeAll
static void beforeAll() {
log.info("execute beforeAll");
}
/**
在所有测试方法执行后被执行
*/
@AfterAll
static void afterAll() {
log.info("execute afterAll");
}
/**
每个测试方法执行前都会执行一次
评论