Spring mvc 在Spring中测试控制器时模拟Web安全依赖关系
要对我的控制器进行快速测试,我想使用Spring mvc 在Spring中测试控制器时模拟Web安全依赖关系,spring-mvc,testing,spring-security,Spring Mvc,Testing,Spring Security,要对我的控制器进行快速测试,我想使用@WebMvcTest。我为控制器编写了服务器端单元测试。这些基本上是涉及切片Spring应用程序上下文的简单单元测试: @WebMvcTest(DemoController.class) class DemoControllerTests { @Autowired private MockMvc mockMvc; @Test @WithAnonymousUser void shouldNotHaveAccessWh
@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
中开始涉及更多依赖项,比如myuserdetails服务(它本身依赖于UserObjectRepository
),问题就开始出现了
@Autowired
public WebSecurityConfig(final MyUserDetailsService myUserDetailsService) {
this.myUserDetailsService = myUserDetailsService;
}
当我运行测试时,Spring无法加载ApplicationContext(NoSuchBeanDefinitionException:没有“com.example.demo.MyUserDetailsService”类型的合格bean可用
)
当我查看@WebMvcTest
的文档时,这是有意义的。它说组件、服务和存储库不会自动配置。但在最后一节中,它说当使用此注释时,将自动配置Spring Security。可以使用@AutoConfigureMockMvc
进行其他配置
在我看来,没有什么特别的事情要做,即使我想在@AutoConfigureMockMvc
中设置安全
配置,它在默认情况下是启用的,不推荐使用。他们提到,secure
属性从2.1.0开始就被弃用,取而代之的是SpringSecurity的测试支持。但是我找不到关于这个主题的专用Spring安全测试支持的更多细节(我已经在测试中使用了@WithMockUser
等)
*
*使用此批注将禁用完全自动配置,而仅应用
*与MVC测试相关的配置(即{@code@Controller}),
*{@code@ControllerAdvice},{@code@JsonComponent},
*{@code Converter}/{@code GenericConverter},{@code Filter},{@code WebMVCConfiguer}
*和{@code HandlerMethodArgumentResolver}bean,而不是{@code@Component},
*{@code@Service}或{@code@Repository}bean)。
*
*默认情况下,用{@code@WebMvcTest}注释的测试也将自动配置Spring
*安全性和{@link MockMvc}(包括对HtmlUnit WebClient和Selenium的支持
*网络驱动程序)。为了更细粒度地控制MockMVC
*可以使用{@link AutoConfigureMockMvc@AutoConfigureMockMvc}注释。
*
一般来说,这些测试都很好。他们测试控制器方法及其方法安全配置。当我添加更多的依赖项和独立的类,然后尝试将它们注入我的WebSecurityConfig
时,问题才开始出现
我如何模拟这些依赖项,以便我的控制器测试使用切片上下文,而不是使用@springbootest
启动整个应用程序上下文?因此安全配置显然已加载,否则您就不必麻烦使用@WithMockUser
等。然后您可以使用Spring的@MockBean
对WebSecurity配置中的模拟依赖项的注释
可用于向弹簧添加模拟的注释
应用程序上下文
为了避免测试类中的重复,可以创建控制器测试扩展的抽象基类测试:
public abstract class BaseControllerTest{
@MockBean
private UserDetailsService userDetailsService;
}
这个案子就应该这样了。对于您需要控制行为的任何模拟bean,您可以使用标准的Mockito功能。因此,安全配置显然已加载,否则您就不必为mockuser
等而烦恼了。然后,您可以使用Spring的@MockBean
注释来模拟WebSecurity配置中的依赖项
可用于向弹簧添加模拟的注释
应用程序上下文
为了避免测试类中的重复,可以创建控制器测试扩展的抽象基类测试:
public abstract class BaseControllerTest{
@MockBean
private UserDetailsService userDetailsService;
}
这个案子就应该这样了。对于您需要控制行为的任何模拟bean,您可以使用标准的Mockito功能。您可以添加控制器代码吗?无论如何,您可以使用
@MockBean
注释来模拟这些依赖关系:是的,我可以使用@MockBean
模拟控制器的依赖关系,但这里不是这样。我在我的WebSecurityConfig
中有依赖项,而不是在控制器中。正如我提到的文档所指出的,@MockBean
在spring上下文中模拟bean,而不是在控制器中。您是否使用@RunWith(SpringRunner.class)
运行测试,但这意味着我必须在使用安全性的每个测试中模拟来自WebSecurityConfig
的依赖项。这意味着整个应用程序中的每个控制器。这对我来说没有意义。你能添加你的控制器代码吗?无论如何,您可以使用@MockBean
注释来模拟这些依赖关系:是的,我可以使用@MockBean
模拟控制器的依赖关系,但这里不是这样。我在我的WebSecurityConfig
中有依赖项,而不是在控制器中。正如我提到的文档所指出的,@MockBean
在spring上下文中模拟bean,而不是在控制器中。您是否使用@RunWith(SpringRunner.class)
运行测试,但这意味着我必须在使用安全性的每个测试中模拟来自WebSecurityConfig
的依赖项。这意味着整个应用程序中的每个控制器。这对我来说毫无意义。