使用@WebMvcTest测试控制器报Failed to load ApplicationContext错误如何解决
@WebMvcTest 是Spring Boot提供的Web层切片测试注解,默认仅会扫描并加载你指定的Controller相关的Bean,不会加载@Service、@Repository、普通@Component等其他层的组件,也不会启动完整的Spring上下文。
你报错的触发逻辑是:项目中存在全局切面/ControllerAdvice 类 lookupAdviceExtend,这个类依赖了lookupMessageService,而Service又依赖LookupMessageRepository,这些依赖都不在@WebMvcTest的默认扫描范围内,所以上下文加载时找不到对应的Bean抛出异常。
而@SpringBootTest是全量上下文加载,会加载所有扫描到的Bean,所以不会出现找不到的问题。
方案1:Mock不需要的依赖(最推荐,符合切片测试的隔离原则)
直接在测试类上加@MockBean注解,模拟缺失的Bean,Spring会自动注入模拟对象替代真实实现,不需要加载真实的Service、Repository层组件。
同时你原来的测试代码存在冗余配置:@WebMvcTest已经自动完成了MockMvc的配置,无需手动build,也不需要额外加@WebAppConfiguration注解。
修正后的测试代码示例:
package controller.v1; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.test.web.servlet.MockMvc; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import io.scbtechx.buzz.mastercommon.repository.LookupMessageRepository; @WebMvcTest(BackendController.class) public class ControllerMockMVCTest { // 直接自动注入已经配置好的MockMvc @Autowired private MockMvc mockMvc; // Mock缺失的Repository,上层依赖的Service也会自动使用模拟的Repository完成注入 @MockBean private LookupMessageRepository lookupMessageRepository; @Test public void test() throws Exception { // 测试逻辑 } }
如果模拟Repository之后还提示Service或者Advice缺失,同理加对应的@MockBean即可。
方案2:排除不需要的全局组件
如果本次测试不需要用到lookupAdviceExtend这个全局增强,可以配置@WebMvcTest的过滤规则,直接排除该类的加载:
@WebMvcTest( value = BackendController.class, excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = LookupAdviceExtend.class ) )
方案3:导入需要的真实Bean(不推荐,破坏切片测试的轻量性)
如果测试必须用到这些组件的真实实现,可以用@Import注解手动导入需要的类:
@WebMvcTest(BackendController.class) @Import({LookupMessageService.class, LookupMessageRepository.class}) // 如果是JPA Repository还需要补充@AutoConfigureDataJpa注解启动JPA相关配置
内容的提问来源于stack exchange,提问作者vishalsha95570

