Spring+JPA+Junit Jupiter+Liquibase栈测试RestController时mock Liquibase问题
解决方案
核心问题原因
你使用@SpringBootTest注解会加载全量应用上下文,即使关闭了Liquibase,Spring Boot的JDBC/JPA自动配置仍会尝试初始化数据源相关Bean,因此抛出JDBCEnvironment创建失败的异常。
具体修复步骤
1. 调整测试注解(优先推荐方案)
改用@WebMvcTest注解替代@SpringBootTest,该注解仅加载Controller层相关组件,不会初始化数据库、JPA、Liquibase等非Web层依赖,完全避免数据库连接请求。
2. 补充test环境配置
在src/test/resources下新建application-test.yml(或properties格式文件),添加如下配置:
spring: liquibase: enabled: false # 排除所有数据库相关自动配置,彻底避免初始化数据库组件 autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration - org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration - org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration - org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
3. 调整测试类代码
将测试类中的@Mock替换为Spring Boot测试提供的@MockBean,实现Mock对象对Spring上下文中原生Bean的替换,Service、Repository都可以用该注解统一Mock:
// 仅加载目标Controller,不需要加载全量上下文 @WebMvcTest(BridgeConfigurationController.class) @AutoConfigureMockMvc(addFilters = false) // 关闭Security过滤器,避免接口鉴权拦截 @ActiveProfiles("test") public class BridgeConfigurationControllerTest { @Autowired MockMvc mockMvc; // 用@MockBean替换Spring上下文里的实际Bean @MockBean BridgeConfigService bridgeConfigService; @MockBean private AccountNumberService accountNumberService; // 如果有依赖的Repository,同样用@MockBean注入即可 // @MockBean // private BridgeConfigRepository bridgeConfigRepository; @Test public void saveBridgeConfigShouldReturnOkOnGoodPayLoad() throws Exception { BridgeConfigurations bridgeConfigurations = mockPayLoad("dbWrite"); GenericResponse bridgeConfigByNameResponse = GenericResponse.createErrorResponse(""); when(bridgeConfigService.findBridgeConfigByNameExactMatchIgnoreCase(any())).thenReturn(bridgeConfigByNameResponse); List<String> allAccountNumbersList = bridgeConfigurations.getAccountNumbers().stream().map(Object::toString).collect(Collectors.toList()); when(accountNumberService.getValidAccountNumbers(any())).thenReturn(allAccountNumbersList); GenericResponse genericResponse = GenericResponse.createSuccessResponse(); genericResponse.setResponse(mockPayLoad("dbWrite")); when(bridgeConfigService.save(any(BridgeConfigurations.class))).thenReturn(genericResponse); mockMvc.perform(post("/api/bridgeconfig/") .contentType(MediaType.APPLICATION_JSON) .content(mockPayLoad("good").toString())) .andExpect(status().isOk()); } }
4. 验证Maven执行配置
你当前pom.xml中的maven-surefire-plugin版本已经支持JUnit Jupiter,无需额外调整,直接执行mvn test即可正常运行所有测试。
特殊场景兼容(必须使用@SpringBootTest的情况)
如果因为业务需要必须加载全量上下文,可以在测试类中手动Mock数据源Bean,覆盖原生的数据源初始化逻辑:
@SpringBootTest @AutoConfigureMockMvc @ActiveProfiles("test") public class BridgeConfigurationControllerTest { // Mock数据源,避免发起实际连接 @MockBean private DataSource dataSource; // 其余代码保持不变 }
同时保留application-test.yml中关闭Liquibase的配置即可。
内容的提问来源于stack exchange,提问作者MFEB
相关产品推荐
相关产品推荐

