SpringBoot 3.2.2集成测试中MockMvc与Mock仓库Bean为空求助
问题:SpringBoot 3.2.2集成测试中MockBean与MockMvc注入失败
核心问题
- 标注
@MockBean的DeliveryRepository、UserRepository始终为空 - 疑惑为何必须手动模拟所有依赖Bean,是否存在自动模拟方式
- 使用
@WebMvcTest或@SpringBootTest+@AutoConfigureMockMvc时,@Autowired的MockMvc始终为空,不愿手动通过MockMvcBuilders初始化
已尝试操作
- 移除
@WebMvcTest(DeliveryController.class),改用以下注解组合:
@RunAs("SpringRunner.class") @SpringBootTest @AutoConfigureMockMvc
- 拒绝使用手动初始化代码:
@BeforeEach void setUp() { this.mockMvc = MockMvcBuilders.standaloneSetup(new DeliveryController(new DeliveryServiceImpl())).build(); }
当前测试类代码
@WebMvcTest(DeliveryController.class) public class DeliveryControllerTest { @Autowired private static MockMvc mockMvc; @MockBean private DeliveryRepository deliveryRepository; // Mocking the repository @MockBean private UserRepository userRepository; // Mocking the repository @Test public void testCreateDelivery() throws Exception { DeliveryEntity delivery = DeliveryEntity.builder().deliveryId(1L).description("Test package").build(); Mockito.when(deliveryRepository.save(Mockito.any(DeliveryEntity.class))).thenReturn(delivery); mockMvc.perform(get("/deliveries/1").contentType(MediaType.APPLICATION_JSON).content("{\"description\": \"Test package\"}")) .andExpect(status().isOk()); Mockito.verify(deliveryRepository, Mockito.times(1)).save(Mockito.any(DeliveryEntity.class)); } // Add more test methods for other endpoints }
POM依赖配置
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-hateoas</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </exclusion> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-docker-compose</artifactId> <scope>runtime</scope> <optional>true</optional> </!dependency --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.4.1.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> </dependencies>
解决方案
1. 修复MockMvc注入失败
测试类中mockMvc被定义为static,Spring无法注入静态字段,直接移除static修饰符:
@Autowired private MockMvc mockMvc; // 去掉static
2. 解决MockBean为空与依赖模拟问题
- 为何需要手动Mock依赖:
@WebMvcTest仅加载控制器相关Bean(控制器、转换器、过滤器等),不会加载Service、Repository等业务层Bean,因此必须用@MockBean模拟控制器依赖链中的所有Bean。 - 自动模拟方式:可以使用
@MockBean的批量模拟(比如直接Mock整个Service层),或结合@SpringBootTest+@MockBean(但会加载完整上下文,测试速度较慢);也可使用@SpyBean配合@Autowired,但仍需确保依赖链完整。 - 注意Spring Boot 3.x默认使用JUnit 5,无需添加
@RunWith(SpringRunner.class),@WebMvcTest已包含@ExtendWith(SpringExtension.class)。
3. 修正测试方法逻辑错误
测试中用get请求却传入JSON内容不符合规范,创建资源应使用post请求:
mockMvc.perform(post("/deliveries") .contentType(MediaType.APPLICATION_JSON) .content("{\"description\": \"Test package\"}")) .andExpect(status().isOk());
4. 消除依赖冲突
POM中手动指定的hibernate-core版本可能与Spring Boot 3.2.2默认版本冲突,建议移除该手动依赖,使用Spring Boot版本管理:
<!-- 移除以下手动指定的依赖 --> <!-- <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.4.1.Final</version> </dependency> -->
内容的提问来源于stack exchange,提问作者Sofiane
相关产品推荐
相关产品推荐

