【发布时间】:2019-07-30 12:21:49
【问题描述】:
为了对我的控制器进行快速测试,我想使用@WebMvcTest。我为控制器编写了服务器端单元测试。这些基本上是涉及切片 Spring 应用程序上下文的简单单元测试:
@WebMvcTest(DemoController.class)
class DemoControllerTests {
@Autowired
private MockMvc mockMvc;
@Test
@WithAnonymousUser
void shouldNotHaveAccessWhenAnonymous() throws Exception {
this.mockMvc.perform(get("/"))
.andExpect(status().isUnauthorized());
}
@Test
@WithMockUser(username = "pascal", roles = "USER")
void shouldHaveAccessWithUserRole() throws Exception {
this.mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello"));
}
}
控制器如下所示:
@RestController
class DemoController {
@GetMapping("/hello")
public String hello() {
return "Hello";
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public String admin() {
return "Admin";
}
}
但是一旦开始在我的WebSecurityConfig 中涉及更多依赖项,例如MyUserDetailsService(它本身依赖于UserObjectRepository),问题就会开始出现。
@Autowired
public WebSecurityConfig(final MyUserDetailsService myUserDetailsService) {
this.myUserDetailsService = myUserDetailsService;
}
当我运行测试时,Spring 无法加载 ApplicationContext (NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.MyUserDetailsService' available)。
当我查看@WebMvcTest 的文档时,这确实是有道理的。它说组件、服务和存储库不会自动配置。但在最后一节中,它说 Spring Security 将在使用此注释时自动配置。可使用@AutoConfigureMockMvc 进行其他配置。
从我的角度来看,没有什么特别的事情要做,即使我想在@AutoConfigureMockMvc 中设置secure 配置,它在默认情况下已启用并已弃用。他们提到 secure 属性自 2.1.0 起已弃用,以支持 Spring Security 的测试支持。但我找不到有关此主题的专用 Spring Security 测试支持的更多详细信息(我已经在我的测试中使用 @WithMockUser 等)
* <p>
* Using this annotation will disable full auto-configuration and instead apply only
* configuration relevant to MVC tests (i.e. {@code @Controller},
* {@code @ControllerAdvice}, {@code @JsonComponent},
* {@code Converter}/{@code GenericConverter}, {@code Filter}, {@code WebMvcConfigurer}
* and {@code HandlerMethodArgumentResolver} beans but not {@code @Component},
* {@code @Service} or {@code @Repository} beans).
* <p>
* By default, tests annotated with {@code @WebMvcTest} will also auto-configure Spring
* Security and {@link MockMvc} (include support for HtmlUnit WebClient and Selenium
* WebDriver). For more fine-grained control of MockMVC the
* {@link AutoConfigureMockMvc @AutoConfigureMockMvc} annotation can be used.
* <p>
测试总体上都很好。他们测试控制器方法及其方法安全配置。当我添加更多依赖项和单独的类时,问题才开始出现,然后我尝试将它们注入我的WebSecurityConfig。
如何模拟这些依赖项,以便我的控制器测试使用切片上下文,而不是使用 @SpringBootTest 启动整个应用程序上下文?
【问题讨论】:
-
你能添加你的控制器代码吗?无论如何,您可以使用
@MockBean注释来模拟这些依赖项:docs.spring.io/spring-boot/docs/current/api/org/springframework/… -
是的,我可以用
@MockBean模拟控制器的依赖关系,但这里不是这样。我的WebSecurityConfig中有依赖项,而不是控制器中。 -
作为我提到的文档,
@MockBean在 spring 上下文中模拟 bean,而不是控制器。 -
你在用
@RunWith(SpringRunner.class)运行你的测试 -
是的,
@MockBean可以做到这一点,但这意味着我必须在使用 Security 的每个测试中模拟来自WebSecurityConfig的依赖项。这意味着整个应用程序中的每个控制器。这对我来说没有意义。
标签: spring-mvc testing spring-security