Spring Boot测试自定义Filter时如何配置虚拟ApplicationContext解决配置缺失报错
报错原因
你遇到的报错是因为当前项目没有被@SpringBootConfiguration标注的配置类(正式项目里通常就是带@SpringBootApplication注解的启动类,该注解默认继承了@SpringBootConfiguration),所以@SpringBootTest无法自动识别到配置来加载ApplicationContext。
另外注意你现有测试代码里的import org.springframework.mock.web.属于未完成的导入语句,需要先删除或补全,否则会先出现编译错误。
解决方案
针对你仅需测试单个自定义Filter的场景,提供两种可行方案:
方案一:轻量手动构造MockMvc(推荐)
不需要启动完整Spring上下文,直接手动注册Filter和虚拟测试接口即可完成测试,执行速度快、调试成本低:
package org.example.filters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; public class LocaleFilterIntegrationTest { private MockMvc mvc; @BeforeEach void setUp() { // 实例化待测试的自定义Filter LocaleFilter localeFilter = new LocaleFilter(); // 构造虚拟测试Controller,模拟业务接口接收请求 TestController testController = new TestController(); // 注册Filter和测试Controller到MockMvc,指定Filter拦截路径 mvc = MockMvcBuilders.standaloneSetup(testController) .addFilter(localeFilter, "/*") .build(); } @RestController static class TestController { @GetMapping("/") public String testEndpoint() { return "ok"; } } @Test public void noLanguageShouldRedirectToSplash() throws Exception { mvc.perform(get("/").contentType(MediaType.TEXT_HTML)).andExpect(status().isOk()); } }
方案二:使用SpringBootTest加载上下文
如果需要依赖Spring上下文的其他能力,可以在测试类中添加内部配置类作为虚拟启动类:
package org.example.filters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; // 指定测试用的配置类 @SpringBootTest(classes = LocaleFilterIntegrationTest.TestConfig.class) @AutoConfigureMockMvc public class LocaleFilterIntegrationTest { @Autowired private MockMvc mvc; // 测试用内部配置类,代替正式项目的启动类 @Configuration static class TestConfig { // 注册自定义Filter到Spring上下文 @Bean public LocaleFilter localeFilter() { return new LocaleFilter(); } // 注册测试用Controller @Bean public TestController testController() { return new TestController(); } } @RestController static class TestController { @GetMapping("/") public String testEndpoint() { return "ok"; } } @Test public void noLanguageShouldRedirectToSplash() throws Exception { mvc.perform(get("/").contentType(MediaType.TEXT_HTML)).andExpect(status().isOk()); } }
内容的提问来源于stack exchange,提问作者errorline1
相关产品推荐
相关产品推荐

