文章目录
前言
所谓单元测试,就是针对最小的功能单元,编写测试代码对其进行正确性测试。
一、Junit单元测试—普通Java文件
对于普通Java文件的单元测试,由于未使用Maven进行依赖管理,我们需要手动导入依赖文件,这里首先介绍一下IDEA中如何导入依赖。
1. Idea依赖导入方式
- 在模块下创建lib文件夹
- 将需要导入的依赖复制到lib文件夹下
- 点击lib文件夹,右键选择Add as Library
- 选择模块创建(根据实际需求选择即可)
2. Junit的使用
在导入Junit依赖后,我们就可以使用Junit提供的工具进行测试
示例
被测试代码
package day14.MyJunit;
public class MathUtils {
public static int getSum(int a, int b) {
return a + b;
}
public static int subtract(int a, int b) {
return a - b;
}
public static int multiply(int a, int b) {
return a * b;
}
public static int divide(int a, int b) {
return a / b;
}
}
junit测试代码的实现
package day14.MyJunit;
import org.junit.Test;
//第一步: 创建测试类, 测试类的类名一般是: 被测试类类名 + Test
public class MathUtilsTest {
/*
第二步: 为了保证每个方法独立, 为测试的每个方法单独创建测试方法
测试方法要求(规格):
(1) 不能有参数
(2) 不能返回值
(3) 方法名建议: test+被测试的方法(遵循驼峰命名规范)
(4) 修饰符必须是public
*/
// 第三步: 为了保证每个测试方法都能够独立运行,需要加上一个注解@Test
/*
@Test : 可以让测试方法独立运行 (核心注解)
@Before(@BeforeEach): 在每个测试方法运行之前都运行一次
@After(@AfterEach): 在每个测试方法运行之后都运行一次
@BeforeClass(@BeforeAll): 在类加载的时候走一次(该注解修饰的测试方法必须是静态方法)
@AfterClass(@AfterAll) : 在所有的测试方法走完之后走一次(同样只能修饰静态方法 就是静态代码块)
总结:
使用步骤:
(1) 导包
(2) 创建测试类:
类名要求: 要测试的类+Test
(3) 在测试类中定义测试方法
方法要求:
(1) 没有返回值, 没有参数
(2) 权限修饰符必须是public
(3) 方法名要求:test+要被测试的方法名
(4) 抗上@Test即可
优点:
(1) 每个方法测试都单独测试互不影响
(2) 自动化测试
(3) 能够生成测试报告
(4) 还可以断言Assert
*/
/*
断言:所谓断言:意思是程序员可以预测程序的运行结果,检查程序的运行结果是否与预期一致。
由junit的Asset工具类实现
eg: Assset.assrtEquals("提示消息",预期目标,实际结果);
*/
@BeforeClass
public static void beforeOne(){
System.out.println("我只走一次");
}
@AfterClass
public static void afterOne(){
System.out.println("我只走一次");
}
@Test
public void textGetsum(){
System.out.println(MathUtils.getSum(10086, 10010));
}
@Test
public void testSubtract(){
System.out.println(MathUtils.subtract(10086, 10010));
}
@Test
public void testMultiply(){
System.out.println(MathUtils.multiply(10086, 10010));
}
@Test
public void testDivide(){
System.out.println(MathUtils.divide(10086, 10010));
}
@Before
public void before(){
System.out.println("加载资源");
}
@After
public void afer(){
System.out.println("释放资源");
}
@Test
public void textGetSum(){
int sum = MathUtils.getSum(10, 20);
Assert.assertEquals("提示消息",40,sum);
}
}
Asset类方法展示
上述断言测试结果
二、Junit单元测试—Maven
- 在pom.xml中,引入JUnit的依赖。
<!--Junit单元测试依赖-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>
- 在test/java目录下,创建测试类,并编写对应的测试方法,并在方法上声明@Test注解。
1. 普通测试
被测试类
package org.example;
public class UserService {
//身份证号---多少岁
//412821200109114459
public int getAge(String card){
return (2024 - Integer.parseInt(card.substring(6, 10)));
}
}
测试类1
import org.example.UserService;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Test;
public class UserServiceTest {
@Test
public void testGetAge(){
int age = new UserService().getAge("412821200109114459");
System.out.println(age);
Assertions.assertEquals(23,age,"结果有误");
}
@BeforeEach
public void beforeEach(){
System.out.println("每个方法执行之前,都先执行我");
}
@BeforeAll
public static void beforeAll(){
System.out.println("我在类加载的时候加载一次");
}
@AfterEach
public void afterEach(){
System.out.println("每个方法执行执行之后,我都要执行");
}
@AfterAll
public static void afterAll(){
System.out.println("我在所以方法执行结束时执行一次");
}
}
2. 单参数测试
@DisplayName注解和(@ParameterizedTest,@ValueSource注解)
import org.example.UserService;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
//设置执测试类名 默认为类名
@DisplayName("测试-学生业务")
public class UserServiceTest {
//设置测试方法名 默认为方法名
@DisplayName("测试-学生年龄")
@Test
public void testGetAge(){
int age = new UserService().getAge("412821200109114459");
System.out.println(age);
Assertions.assertEquals(23,age,"结果有误");
}
@DisplayName("多参数测试-学生年龄")
//标志,代表有参数测试
@ParameterizedTest
//设置测试参数 方法测试方法会依次遍历注解数组中的元素
@ValueSource(strings={"412821196245632147","412821196214141118","145987196212354415"})
public void testGetAges(String s){
int age = new UserService().getAge(s);
//断言
Assertions.assertEquals(62,age,"戳");
}
}
测试结果
@ValueSoure注解源码
3. 多参数测试
@CsvSource注解
/*
@CsvSource 是一个在 JUnit 5 中用于提供测试数据的注解,特别是在参数化测试中非常有用。它允许你以逗号分隔值(CSV)
格式直接在测试类中定义测试数据,并且这些数据会被自动注入到测试方法中。
基本用法
@CsvSource 注解可以被用在 @ParameterizedTest 上,来为测试方法提供一组或多组参数。每组参数都是一行CSV格式的数据,
其中每个值由逗号分隔。
*/
@ParameterizedTest
@CsvSource({"lvbu,123456", "xiaoqiao,123456"}) //每个字符串数组的元素都是一组数据
public void testQuery(String username , String password) { //方法参数与每组数据对应,方法会依次测试每组数据
//方法体
}
/*
CSV 文件的基本结构
分隔符:最常用的分隔符是逗号(,),但也可以使用其他字符,比如制表符(\t)、竖线(|)等。
行:每行代表一条记录或一行数据。
列:每列代表一个特定的属性或字段。
CSV 文件的例子
Alice,22,New York
Bob,25,Los Angeles
*/
@CsvFileSource注解 读取CSV文件中数据
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import java.sql.*;
public class JDBCDQLTest {
@Test
@ParameterizedTest
@CsvFileSource(resources = "jdbctest.csv") //该注解可以读取csv文件中内容,每一行为一组
public void testDqlJDBC(String _name,String _password) throws ClassNotFoundException, SQLException {
//链接数据库
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "JDBC:mysql://localhost:3306/itheima";
Connection connection = DriverManager.getConnection(url, "root", "root");
//获取数据库执行对象
Statement statement = connection.createStatement();
//执行SQL语句
ResultSet resultSet = statement.executeQuery("select * from user where username ='"+ _name+"'and password = '"+_password+"'");
//读取结果中的语句
while (resultSet.next()){
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println("id:"+id+" username:"+username+" name:"+name+" age:"+age);
}
//关闭资源
connection.close();
statement.close();
}
}
三、Junit单元测试—SpringBoot项目
在SpringBoot项目中,如果只是进行简单的单元测试,这直接按照上述Maven操作即可,但如果测试需要获取项目上下文内容(也就是Bean),则需要创建与主配置类结构一致的测试类,并加上引入@SpringBootTest
1. 使用步骤
- 引入Maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
- 创建测试类
- 引入@SpringBootTest注解
- 进行测试操作,使用注解进行测试即可
2. @SpringBootTest详解
- @SpringBootTest 是 Spring Boot 提供的一个注解,用于启动一个完整的 Spring Boot 应用程序上下文,并在其中执行测试。这个注解通常用于集成测试,因为它可以模拟完整的应用程序环境,包括配置文件、自动装配的 Bean、以及依赖项等。
- @SpringBootTest 注解可以被应用在一个测试类上,它会启动一个完整的 Spring Boot 应用程序上下文,并加载所有的 Bean。(扫描相同包结构下对应的主配置类,或者classes指定的住配置类,SpringBoot项目中导入spring-boot-startr-test后测试类和包结构会自动生产,该注解包含了junit单元测试注解,所以实际上用的还是junit)
示例
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ApplicationContextTest {
@Autowired
private SomeService someService;
@Test
public void contextLoads() {
// 这里可以验证应用程序上下文是否正确加载
// 例如,验证某些 Bean 是否正确初始化
assert someService != null;
}
}
/*
在这个例子中:
● @SpringBootTest 注解启动了一个完整的 Spring Boot 应用程序上下文。
● @Autowired 注入了一个 SomeService Bean,用于测试。
*/
- 配置选项
- @SpringBootTest 注解还提供了一些可选的配置选项,用于控制应用程序上下文的加载方式:
- webEnvironment:指定是否启动 Web 环境。可以选择 WebEnvironment.RANDOM_PORT、WebEnvironment.DEFINED_PORT 或 WebEnvironment.NONE。
- classes:指定要加载的主配置类(就是引导类,启动类)。
- properties:指定要在测试期间覆盖的属性。
- @SpringBootTest 注解还提供了一些可选的配置选项,用于控制应用程序上下文的加载方式:
示例 通过classes指定后,这不必须与主配置类结构一致
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = Application.class,
properties = {"server.port=0", "spring.datasource.url=jdbc:h2:mem:testdb"})
public class ApplicationContextTest {
@Autowired
private SomeService someService;
@Test
public void contextLoads() {
// 这里可以验证应用程序上下文是否正确加载
// 例如,验证某些 Bean 是否正确初始化
assert someService != null;
}
}
/*
● webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
表示启动一个随机端口的 Web 环境。
● classes = Application.class 指定主配置类。
● properties 用于覆盖配置文件中的属性。
*/
- 使用 @RunWith(SpringRunner.class)
在 JUnit 4 中,你需要使用 @RunWith(SpringRunner.class) 来启动 Spring Boot 应用程序上下文。但在 JUnit 5 中,Spring Boot 已经默认使用了 SpringRunner,因此不再需要显式声明。
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationContextTest {
@Autowired
private SomeService someService;
@Test
public void contextLoads() {
// 这里可以验证应用程序上下文是否正确加载
// 例如,验证某些 Bean 是否正确初始化
assert someService != null;
}
}