Java 中使用Mockito 模拟对象的单元测试的快速示例
Mockito是一个流行的Java模拟框架,它允许你在单元测试中创建和配置模拟对象,以便在测试过程中替换那些不容易构造或获取的对象。
Mockito可以与JUnit无缝集成,下面的示例演示 Mockito + JUnit实现模拟对象的单元测试。
依赖导入
这里使用Maven进行依赖的管理, 在pom.xml 中需要导入JUnit 和Mockito相关的依赖。
<?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.osxm.test.javaut</groupId>
<artifactId>java-unittest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<junit.jupiter.version>5.11.0</junit.jupiter.version>
<junit.platform.version>1.9.3</junit.platform.version>
</properties>
<dependencies>
<!-- JUnit Jupiter API for writing tests -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<!-- JUnit Jupiter Engine for executing tests -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
<scope>test</scope>
</dependency>
<!-- (Optional) Only required to run tests in an IDE
without built-in support for JUnit 5
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency> -->
<!-- Mockito核心依赖 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.14.2</version>
<scope>test</scope>
</dependency>
<!-- 如果需要Mockito的JUnit集成,可以添加以下依赖 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.14.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- junit-jupiter-api : 在写测试的时候需要导入的一些JUnit 的类
- junit-jupiter-engine 运行JUnit 测试的引擎
- junit-platform-launcher 一般不需要导入,用于在不内置支持JUnit5的IDE运行
- mockito-core ,Mockito核心依赖 ,包括mockito的一些类和注解。
- mockito-junit-jupiter: Mockito与JUnit的集成
源代码
MyService
是一个服务类 ,它依赖于MyDependency
。 在MyService
的 myServiceMethod
方法中会调用 MyDependency
的 getData()
方法。
/**
* Copyright (C) Oscar Chen(XM):
*
* Date: 2024-11-10
* Author: XM
*/
package com.osxm.test.mock;
public class MyService {
private MyDependency myDependency;
// 构造函数注入依赖
MyService(MyDependency myDependency) {
this.myDependency = myDependency;
}
// 被测试的方法
String myServiceMethod() {
String data = myDependency.getData();
return "processed " + data;
}
}
/**
* Copyright (C) Oscar Chen(XM):
*
* Date: 2024-11-10
* Author: XM
*/
package com.osxm.test.mock;
public class MyDependency {
String getData() {
// 真实实现,但在测试中会被模拟
return "real data";
}
}
Mock 单元测试
Mock的单元测试代码如下:
/**
* Copyright (C) Oscar Chen(XM):
*
* Date: 2024-11-10
* Author: XM
*/
package com.osxm.test.mock;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class MyServiceTest {
@Mock
private MyDependency myDependency; // 创建一个模拟对象
@InjectMocks
private MyService myService; // 创建一个被测试对象,并注入模拟对象
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this); // 初始化模拟对象
}
@Test
void testMyServiceMethod() {
// 设置模拟对象的行为
when(myDependency.getData()).thenReturn("mocked data");
// 调用被测试对象的方法
String result = myService.myServiceMethod();
// 验证结果
assertEquals("processed mocked data", result);
// 验证模拟对象的方法是否被调用
verify(myDependency).getData();
}
}
在测试中,
- 使用
@Mock
注解来创建MyDependency
的模拟对象, - 并使用
@InjectMocks
注解来创建MyService
的实例,同时将模拟对象注入其中。 - 然后,使用
when
和thenReturn
方法来设置模拟对象的行为 - 最后调用被测试对象的方法并验证结果和交互。
请注意,上述示例中的MockitoAnnotations.openMocks(this)
方法是在JUnit 5中初始化Mockito注解的推荐方式。如果你使用的是JUnit 4,则应使用MockitoAnnotations.initMocks(this)
方法。此外,如果使用的是@RunWith(MockitoJUnitRunner.class)
注解来运行测试,则无需手动调用初始化方法,因为MockitoJUnitRunner
会自动处理。
运行
在VS Code中运行的效果如下: