1、SpringBoot集成Junit5
我在测试中使用的SpringBoot版本为3.0.5,在SpringBoot3中引入Junit5只需要添加三个Junit5的三个依赖,并不需要指定版本号,SpringBoot已经为我们管理好了依赖的版本号。
<!--Junit5依赖-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
2、SpringBoot集成Mockito
<!--Mockito依赖-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!--模拟静态方法所需要的依赖-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<!--Mockito集成到Junit5-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
3、准备一个需要被测试的方法
我这里写了一个service,业务是对传入的学生对象验证生日信息是否正确,如果正确则为学生添加学号信息后存入数据库。
@Component
@Slf4j
public class StudentServiceImpl implements StudentService {
@Resource
private StudentDao studentDao;
@Override
public void addStudent(Student student) {
log.info("新增学生{}", student);
// 校验数据
if (student.getBirthday() == null) {
throw new VerifyException("请输入学生生日");
}
if (!VerifyUtil.verifyIsDateFormat(student.getBirthday())) {
throw new VerifyException("学生生日格式有误");
}
// 添加学号
student.setStudentCode(CodeUtil.createCode());
// 保存学生
studentDao.insertStudent(student);
}
}
1)工具类VerifyUtil和工具类CodeUtil
工具类VerifyUtil提供了对日期格式的验证
public class VerifyUtil {
public static boolean verifyIsDateFormat(String str) {
String timeRegex1 = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|"+
"((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|"+
"((0[48]|[2468][048]|[3579][26])00))-02-29)$";
return Pattern.matches(timeRegex1, str);
}
}
工具类CodeUtil是生成一个学号,因为这里是测试用例,所以简略返回一个字符串"1001"
public class CodeUtil {
public static String createCode() {
return "1001";
}
}
2)dao层实现
这里只对service层做测试,dao的实现细节就不做展示了,在测试中会使用@Mock注解对这个数据进行模拟,不去执行真实的方法。
4、单元测试
1)在需要被测试的service实现类上Alt+Enter,点击Create Test
2) 根据需要来配置单元测试类
这些都可以在测试类创建完成后修改
3)写测试方法
// 使用了这个注解开启mock能力
@ExtendWith(MockitoExtension.class)
class StudentServiceImplTest {
// 实例化一个模拟的类,@Mock和@Spy注解模拟的类都会被注入到这个类中
@InjectMocks
StudentServiceImpl service;
// 模拟一个类,不会去执行真实方法
@Mock
StudentDao studentDao;
/**
* 在所有测试方法之前执行的方法
*/
@BeforeAll
static void doBefore() {
System.out.println("开始测试");
}
/**
* 在所有测试方法之后执行的方法
*/
@AfterAll
static void doAfter() {
System.out.println("结束测试");
}
/**
* 测试方法
*/
@Test
void addTest() {
Student student = new Student();
// 学生生日为空
try {
service.addStudent(student);
Assertions.fail();
}catch (VerifyException e) {
Assertions.assertEquals("请输入学生生日", e.getMessage());
}
// 学生生日格式有误
student.setBirthday("123");
try {
service.addStudent(student);
Assertions.fail();
}catch (VerifyException e) {
Assertions.assertEquals("学生生日格式有误", e.getMessage());
}
// 打桩 如果调用了createCode()方法则返回固定的"1002"
Mockito.mockStatic(CodeUtil.class).when(CodeUtil::createCode).thenReturn("1002");
// 正确的数据
student.setBirthday("2000-03-21");
service.addStudent(student);
}
}
5、测试结果
测试通过,行覆盖率为100%