目录
Mock 可以理解为创建一个虚拟的对象,在测试环境用来替换真实的对象,从而验证
- 该对象的某些方法,调用次数,参数
- 指定返回结果或指定特定动作
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.mockito</groupId>-->
<!-- <artifactId>mockito-core</artifactId>-->
<!-- <version>4.3.1</version>-->
<!-- </dependency>-->
<!--<!– 包含mockito-core,并且可以支持静态 -->
<!-- 3.4后-->
<!-- 两者不能同时引入-->
<!--–>-->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
案例
package com.example.demo;
/**
* @author: xxx
* @date: 2023/7/11 18:21
*/
public class Demo {
// 静态有参
public static Integer id(Integer id){
return id;
}
// 静态无参
public static String name(){
return "xxx";
}
public int add(int a, int b){
return a + b;
}
}
验证和断言
- 验证:验证待验证的对象是否发生过某些行为
- 断言:判断返回的结果 的 数据类型 是否是我们符合的类型
@SpringBootTest
class DemoApplicationTests {
@Test
void testAdd() {
//mock-一个Random类
Random random = Mockito.mock(Random.class);
System.out.println(random.nextInt());
//验证:验证待验证的对象是否发生过某些行为
// 断言:判断返回的结果 的 数据类型 是否是我们符合的类型
//验证 verify 配合time()使用 可以验证某些操作发生的次数
//表示 调用 random类的 nextInt()函数两次
//如果 不一样 日志会提示
/**
* org.mockito.exceptions.verification.TooFewActualInvocations:
* random.nextInt();
* Wanted 2 times:
* -> at com.example.demo.DemoApplicationTests.testAdd(DemoApplicationTests.java:19)
* But was 1 time:
* -> at com.example.demo.DemoApplicationTests.testAdd(DemoApplicationTests.java:18)
*/
Mockito.verify(random,Mockito.times(2)).nextInt();
//断言
//当调用nextInt()时返回100
Mockito.when(random.nextInt()).thenReturn(100); //打桩
Assertions.assertEquals(100, random.nextInt()); //预期返回值为100
}
}
注解
@Mock
@BeforeEach
@AfterEach
package com.example.demo;
import com.example.demo.annotation.Student;
import org.junit.jupiter.api.*;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Random;
@SpringBootTest
class DemoApplicationTests {
@Mock
private Random random;
// Random random = Mockito.mock(Random.class);
@BeforeEach//在每个测试方法前
void setUp(){
MockitoAnnotations.openMocks(this);//@Mock需要和这个方法一块使用
System.out.println("测试前准备");
}
@AfterEach
void after(){
System.out.println("测试结束");
}
@Test
void testAdd() {
}
}
Spy
- 被spy的对象会走真实的方法,而mock对象不会
- spy()方法的参数是对象实例,mock的参数是class
package com.example.demo;
import com.example.demo.annotation.Student;
import org.junit.jupiter.api.*;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Random;
@SpringBootTest
class DemoApplicationTests {
@Spy
private Demo demo;
// Random random = Mockito.mock(Random.class);
@BeforeEach//在每个测试方法前
void setUp(){
System.out.println("测试前准备");
MockitoAnnotations.openMocks(this);//@Mock需要和这个方法一块使用
}
@AfterEach
void after(){
System.out.println("测试结束");
}
@Test
void testAdd() {
//打桩
Mockito.when(demo.add(1, 2)).thenReturn(0);
//没有打桩的话走真实的方法,打桩的话走,打桩的方法。
/**
* org.opentest4j.AssertionFailedError:
* Expected :3
* Actual :0
* <Click to see difference>
*/
Assertions.assertEquals(3, demo.add(1, 2));
}
}
mock静态方法
- 静态有参
- 静态无参
package com.example.demo;
import com.example.demo.annotation.Student;
import org.junit.jupiter.api.*;
import org.mockito.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Random;
@SpringBootTest
class DemoApplicationTests {
@Spy
private Demo demo;
@BeforeEach//在每个测试方法前
void setUp(){
System.out.println("测试前准备");
MockitoAnnotations.openMocks(this);//@Mock需要和这个方法一块使用
}
@AfterEach
void after(){
System.out.println("测试结束");
}
@Test
void testAdd() {
//抛出一个RuntimeException,用于try catch等测试不同 情况
Mockito.when(demo.add(1,1)).thenThrow(new RuntimeException());
demo.add(1,1);
//走真实的方法
Mockito.when(demo.add(1,2)).thenCallRealMethod();
Assertions.assertEquals(2,demo.add(1,2));
//3.4
}
@Test
void testId(){
//try-resource 关闭资源
try (MockedStatic<Demo> demo = Mockito.mockStatic(Demo.class)) {
demo.when(() -> Demo.id(1)).thenReturn(1);
Assertions.assertTrue(Demo.id(1)==1);
}
}
@Test
void testName(){
try (MockedStatic<Demo> demo = Mockito.mockStatic(Demo.class)) {
demo.when(Demo::name).thenReturn("guitu");
Assertions.assertEquals("xxx",Demo.name());
}
}
}
单元测试实例
【Mockito】单元测试如何提升代码覆盖率_哔哩哔哩_bilibili
来源: