您的位置:首页 > 新闻 > 会展 > 今天出入深圳最新规定_瑞安人才网_seo最新优化技术_商家推广平台有哪些

今天出入深圳最新规定_瑞安人才网_seo最新优化技术_商家推广平台有哪些

2025/5/21 0:57:54 来源:https://blog.csdn.net/u012631267/article/details/144479605  浏览:    关键词:今天出入深圳最新规定_瑞安人才网_seo最新优化技术_商家推广平台有哪些
今天出入深圳最新规定_瑞安人才网_seo最新优化技术_商家推广平台有哪些

Spring Boot 项目中 JUnit 使用总结

在 Spring Boot 项目开发中,spring-boot-starter-test 是一个常用的单元测试依赖库,集成了许多主流测试工具和框架。本文总结了常见的测试场景及 Mock 方法,同时记录了项目中SpringBoot版本升级导致JUnit4升级到JUnit5的必要原因,供参考。

1. spring-boot-starter-test 依赖介绍

spring-boot-starter-test 是 Spring Boot 推荐的测试依赖包,旨在简化测试相关的库配置。
需要显式添加到项目中(通常在 pom.xml 或 build.gradle 中手动引入),它会自动提供一整套测试工具。
spring-boot-starter-test 默认包含以下常用测试工具:

  • JUnit 5 (默认测试框架)
  • Mockito (Mock 工具)
  • AssertJ (更简洁的断言工具)
  • Hamcrest (匹配器断言)
  • JsonPath (JSON 解析工具)
  • Spring Test (测试 Spring 上下文和 Web 工具)

对于特殊场景(例如 Mock 静态方法),需要手动添加 PowerMock 依赖。

2. 常用测试方式与适用场景

测试方式选用场景
Mockito单元测试,模拟依赖;
MockMvc测试 Controller 的逻辑和 HTTP 请求/响应;
@MockBean/@SpyBean替换 Spring 上下文中的 Bean,适用于集成测试;
MockEnvironment模拟 Spring 的环境变量和配置属性;
TestRestTemplate测试整个应用程序的 HTTP 接口(集成测试);
PowerMock需要 Mock 静态方法、构造函数、final 类等复杂场景;

根据需求和测试粒度选择合适的 Mock 方式,例如单元测试推荐 Mockito,集成测试可以选择 TestRestTemplate 或 MockMvc。

3. 示例详解

3.1 Mockito

特点

  • 轻量级:无需启动 Spring 上下文。
  • 用于单元测试,模拟依赖对象的行为。

示例

模拟服务层依赖:

@SpringBootTest
public class UserServiceTest {@Mockprivate UserRepository userRepository; // 模拟依赖@InjectMocksprivate UserService userService; // 将 Mock 对象注入到被测对象中@Testpublic void testGetUserById() {User mockUser = new User(1L, "Alice");Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));User user = userService.getUserById(1L);assertEquals("Alice", user.getName());}
}

3.2 @MockBean 和 @SpyBean

特点

  • Spring 提供的 Mock 对象,集成了 Spring 的上下文。
  • @MockBean:替换 Spring 上下文中的实际 Bean。
  • @SpyBean:部分模拟 + 调用真实方法。

示例

@MockBean

@SpringBootTest
public class UserServiceIntegrationTest {@Autowiredprivate UserService userService;@MockBeanprivate UserRepository userRepository; // Mock Spring 上下文中的 Bean@Testpublic void testGetUserById() {User mockUser = new User(1L, "Alice");// 模拟 findById 方法,其他调用未设置模拟行为的方法返回 "Mockito 默认值(方法返回类型的默认值)Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));User user = userService.getUserById(1L);assertEquals("Alice", user.getName());// 调用未设置模拟行为的 findAllList<User> users = userRepository.findAll();assertTrue(users.isEmpty()); // 默认返回空集合}
}

@SpyBean

@SpringBootTest
public class UserServiceSpyTest {@SpyBeanprivate UserService userService; // 部分 Mock + 调用真实方法@MockBeanprivate UserRepository userRepository;@Testpublic void testGetUserByIdWithSpy() {User mockUser = new User(1L, "Alice");// 模拟 findById 方法,其他调用未设置模拟行为的方法调用真实逻辑Mockito.when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));User user = userService.getUserById(1L); assertEquals("Alice", user.getName());// 调用未模拟的 findAll 方法(真实逻辑)List<User> users = userRepository.findAll();assertFalse(users.isEmpty()); // 调用真实逻辑,返回真实数据assertEquals(2, users.size());}
}

3.3 MockMvc

特点

  • 主要用于测试 Controller 层。
  • 无需启动 Web 服务器,模拟 HTTP 请求和响应。

示例

@WebMvcTest(UserController.class)
public class UserControllerTest {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate UserService userService; // 模拟依赖服务@Testpublic void testGetUserById() throws Exception {User mockUser = new User(1L, "Alice");Mockito.when(userService.getUserById(1L)).thenReturn(mockUser);mockMvc.perform(get("/users/1")).andExpect(status().isOk()).andExpect(jsonPath("$.name").value("Alice"));}
}   

3.4 TestRestTemplate

特点

  • 主要用于集成测试,适合测试 HTTP 接口。
  • TestRestTemplate 是 Spring 提供的工具类,可以方便地测试 HTTP 接口。

示例

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserApiIntegrationTest {@Autowiredprivate TestRestTemplate restTemplate;@Testpublic void testGetUserById() {ResponseEntity<User> response = restTemplate.getForEntity("/users/1", User.class);assertEquals(HttpStatus.OK, response.getStatusCode());assertEquals("Alice", response.getBody().getName());}
}  

3.5 Spring Boot Mock Environment

特点

  • 使用 MockEnvironment 来模拟 Spring 的环境变量和配置属性

示例

@SpringBootTest
public class EnvironmentTest {@Testpublic void testMockEnvironment() {MockEnvironment environment = new MockEnvironment();environment.setProperty("app.name", "TestApp");assertEquals("TestApp", environment.getProperty("app.name"));}
} 

3.6 Mock静态方法 (PowerMock)

特点

  • 需要 Mock 静态方法、final 类时,使用 PowerMock。
  • 需要额外添加依赖。

示例

@RunWith(PowerMockRunner.class)
@PrepareForTest(Utility.class) // 指定需要 Mock 的静态类
public class StaticMethodTest {@Testpublic void testStaticMethod() {PowerMockito.mockStatic(Utility.class);PowerMockito.when(Utility.staticMethod()).thenReturn("Mocked Response");String result = Utility.staticMethod();assertEquals("Mocked Response", result);}
}

Mockito 3.4+ 提供了对静态方法和 final 类的原生支持,而不需要 PowerMock。关于于这部分下文会详细介绍

4.Mock静态方法或final类(特殊性&兼容性)

4.1 JUnit 4 + PowerMock使用场景

在 Spring Boot 项目中,Mock 静态方法或 final 类需要使用 PowerMock,因为 Mockito 默认不支持对静态方法和 final 类的 Mock。以下是配置和实现步骤:

4.1.1 添加依赖

在 Spring Boot 项目中,spring-boot-starter-test 不包含 PowerMock,需要手动添加。

Maven 依赖

<dependency><groupId>org.powermock</groupId><artifactId>powermock-module-junit4</artifactId><version>2.0.9</version> <!-- 确保与项目 JUnit 版本兼容 --><scope>test</scope>
</dependency>
<dependency><groupId>org.powermock</groupId><artifactId>powermock-api-mockito2</artifactId><version>2.0.9</version><scope>test</scope>
</dependency>
<dependency><groupId>org.mockito</groupId><artifactId>mockito-inline</artifactId><version>4.11.0</version> <!-- 支持 final 类的 Mock --><scope>test</scope>
</dependency>
4.1.2 示例
Mock 静态方法

通过 PowerMock 的 mockStatic 方法 Mock 静态方法。

假设我们有一个静态工具类 Utility:

public class Utility {public static String getStaticMessage() {return "Original Message";}
}

测试代码:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;@RunWith(PowerMockRunner.class) // 使用 PowerMockRunner
@PrepareForTest(Utility.class)  // 指定需要 Mock 的类
public class UtilityTest {@Testpublic void testStaticMethod() {PowerMockito.mockStatic(Utility.class); // Mock 静态方法Mockito.when(Utility.getStaticMessage()).thenReturn("Mocked Message");String result = Utility.getStaticMessage();assertEquals("Mocked Message", result); // 验证 Mock 是否生效}
}
Mock Final 类

示例

假设我们有一个 final 类:

public final class FinalClass {public String sayHello() {return "Hello!";}
}

测试代码:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;@RunWith(PowerMockRunner.class) // 使用 PowerMockRunner
@PrepareForTest(FinalClass.class)  // 指定需要 Mock 的类
public class FinalClassTest {@Testpublic void testFinalClassMethod() throws Exception {FinalClass finalClassMock = PowerMockito.mock(FinalClass.class); // Mock Final 类Mockito.when(finalClassMock.sayHello()).thenReturn("Mocked Hello!");String result = finalClassMock.sayHello();assertEquals("Mocked Hello!", result); // 验证 Mock 是否生效}
}
4.1.3 Spring Boot 集成测试中的配置

如果需要在 Spring Boot 的测试中使用 PowerMock,可以将 PowerMockRunner 替换为 Spring 的测试上下文支持。

示例

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.boot.test.context.SpringBootTest;@RunWith(PowerMockRunner.class)
@PrepareForTest(Utility.class) // 指定需要 Mock 的类
@SpringBootTest // 启用 Spring 上下文
public class UtilitySpringBootTest {@Testpublic void testStaticMethodInSpring() {PowerMockito.mockStatic(Utility.class);Mockito.when(Utility.getStaticMessage()).thenReturn("Mocked in Spring Context");String result = Utility.getStaticMessage();assertEquals("Mocked in Spring Context", result);}
}

4.2 JUnit5使用场景

在使用 JUnit 5 的项目中,PowerMock 并未完全支持 JUnit 5,因此无法直接将 PowerMock 与 JUnit 5 一起使用。这是因为 PowerMock 的核心依赖于特定的类加载机制,而 JUnit 5 的架构与 JUnit 4 不同,没有提供类似 Runner 的机制。

JUnit 5使用Mockito-inline有两种方式可以启用对 final 类或静态方法的支持

4.2.1. 在 pom.xml 中添加依赖 方式

直接引入 mockito-inline 的 Maven 依赖,是最简单和推荐的方式。

<!--Maven依赖-->
<dependency><groupId>org.mockito</groupId><artifactId>mockito-inline</artifactId><version>5.x.x</version> <!-- 请根据需要替换为适当版本 --><scope>test</scope>
</dependency>
// gradle依赖
dependencies {testImplementation 'org.mockito:mockito-inline:5.x.x' // 请替换为适当版本
}
4.2.2 使用配置文件 mockito-extensions/org.mockito.plugins.MockMaker方式

如果不引入 mockito-inline 依赖,也可以通过在 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker 文件中添加以下内容来手动开启功能:

mock-maker-inline
两种方式的区别
特性通过依赖启用 (mockito-inline)通过配置文件启用 (mock-maker-inline)
简洁性简单,直接添加依赖即可生效需要手动创建配置文件
粒度控制全局生效,对整个测试项目启用灵活,可按模块或文件级别配置
社区支持官方推荐,现代项目通用方式不再主流,仅适用部分老旧项目
适用性现代项目(Spring Boot、JUnit 5)老旧项目或特殊场景
易维护性高,升级时直接跟随版本低,容易被遗忘或误删
选择建议
  1. 如果可以直接引入依赖,优先使用 mockito-inline 方式,简洁易用。
  2. 如果受环境限制(例如某些构建工具或依赖约束),可以使用配置文件的方式作为替代。
  3. 不建议混用两种方式,可能导致不可预期的问题。
4.2.3 示例
Mock final 类
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;import static org.junit.jupiter.api.Assertions.assertEquals;class FinalClass {public final String sayHello() {return "Hello!";}
}public class FinalClassTest {@Testpublic void testFinalClassMethod() {FinalClass finalClassMock = Mockito.mock(FinalClass.class);Mockito.when(finalClassMock.sayHello()).thenReturn("Mocked Hello!");assertEquals("Mocked Hello!", finalClassMock.sayHello());}
}
Mock 静态方法

Mockito 3.4+ 引入了对静态方法 Mock 的原生支持,推荐使用这种方式。

import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;class Utility {public static String getStaticMessage() {return "Original Message";}
}public class StaticMethodTest {@Testpublic void testStaticMethod() {try (MockedStatic<Utility> mockedStatic = mockStatic(Utility.class)) {mockedStatic.when(Utility::getStaticMessage).thenReturn("Mocked Message");assertEquals("Mocked Message", Utility.getStaticMessage());}}
}

4.3 小结

场景解决方案推荐级别
Mock 静态方法Mockito 3.4+ 原生 MockStatic⭐⭐⭐⭐⭐
Mock final 类或方法Mockito-inline⭐⭐⭐⭐⭐
必须使用 PowerMock回退到 JUnit 4⭐⭐⭐
更复杂需求 (如私有方法等)JMockit⭐⭐⭐

5. SpringBoot版本升级对JUnit的影响

SpringBoot项目升级时( 2.2.5.RELEASE→2.7.18),升级了SpringBoot的版本导致大量的JUnit代码报错,通过Maven依赖源码以及官方资料查询了一番总结如下:

Spring Boot 2.2.5.RELEASE(依赖含JUnit4和JUint5)升级到Spring Boot 2.7.18(依赖只含JUint5)

  • SpringBoot2.2.0之前,spring-boot-starter-test引入的是JUnit4
  • 2.2.0 < SpringBoot < 2.4.0,spring-boot-starter-test默认使用JUnit5,同时也兼容支持JUnit4
  • SpringBoot2.4.0之后,spring-boot-starter-test默认仅支持JUnit5,去掉了兼容JUnit4引擎
附:Maven 层级依赖解析(spring-boot-starter-test)
spring-boot-starter-test|+--> spring-boot-test|+--> spring-boot-test-autoconfigure|+--> 第三方依赖 (JUnit, Mockito, AssertJ, 等)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com