Spring WebMvcTest如何模拟认证?
Spring WebMvcTest how to mock Authentication?
我有一个使用以下方法的控制器。我从方法参数中获取 Authentication
并使用它来获取主体。
@PatchMapping("/{employeeId}/present")
public PersonalDevelopmentPlan savePresent(@PathVariable int employeeId,
@RequestBody PersonalDevelopmentPlan personalDevelopmentPlan,
Authentication authentication) {
EmployeeDetails details = (EmployeeDetails) authentication.getPrincipal();
return pdpService.savePresent(employeeId, personalDevelopmentPlan, details.getEmployee().getId());
}
然后我使用 @WebMvcTest
得到这个测试用例
@Test
@WithMockUser
public void testSavePresent_returns_result_from_service() throws Exception {
PersonalDevelopmentPlan pdp = new PersonalDevelopmentPlan();
pdp.setEmployee(EMPLOYEE_ID);
given(service.savePresent(eq(EMPLOYEE_ID), any(), anyInt())).willReturn(pdp);
mvc.perform(patch(URL_WITH_ID + "/present").secure(true)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pdp)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.employee", Matchers.is(EMPLOYEE_ID)));
}
当我 运行 虽然如此,我在以下行中得到 NullPointerException
:
EmployeeDetails details = (EmployeeDetails) authentication.getPrincipal();
因为身份验证为空。我已经用 @MockUser
注释了测试,但身份验证仍然为空。我如何在控制器方法的参数中模拟身份验证?
我的测试用 @AutoConfigureMockMvc(addFilters = false)
注释
谢谢!
如果您最初有一个用户持久保存在您的数据库中(或者如果您在@PostConstruct 中创建这样的用户),您可以使用@WithUserDetails 注释。
@WithMockUser
这将使用 Authentication 上的 principal is Spring Security 的 User object
虽然 @WithMockUser
是一种非常方便的入门方式,但它可能 并非在所有情况下都有效 。例如,应用程序通常期望 Authentication
主体属于 特定类型 。这样做是为了让应用程序可以将主体称为自定义类型,并减少 Spring 安全性上的耦合。
自定义主体通常由自定义 UserDetailsService
返回,returns 一个同时实现 UserDetails
和自定义类型的对象。对于这种情况,使用自定义 UserDetailsService 创建测试用户很有用。这正是 @WithUserDetails
所做的。
我们可以创建自己的注解,使用@WithSecurityContext 来创建我们想要的任何SecurityContext。例如,我们可以创建一个名为 @WithMockCustomUser 的注解作为 @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
我有一个使用以下方法的控制器。我从方法参数中获取 Authentication
并使用它来获取主体。
@PatchMapping("/{employeeId}/present")
public PersonalDevelopmentPlan savePresent(@PathVariable int employeeId,
@RequestBody PersonalDevelopmentPlan personalDevelopmentPlan,
Authentication authentication) {
EmployeeDetails details = (EmployeeDetails) authentication.getPrincipal();
return pdpService.savePresent(employeeId, personalDevelopmentPlan, details.getEmployee().getId());
}
然后我使用 @WebMvcTest
@Test
@WithMockUser
public void testSavePresent_returns_result_from_service() throws Exception {
PersonalDevelopmentPlan pdp = new PersonalDevelopmentPlan();
pdp.setEmployee(EMPLOYEE_ID);
given(service.savePresent(eq(EMPLOYEE_ID), any(), anyInt())).willReturn(pdp);
mvc.perform(patch(URL_WITH_ID + "/present").secure(true)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pdp)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.employee", Matchers.is(EMPLOYEE_ID)));
}
当我 运行 虽然如此,我在以下行中得到 NullPointerException
:
EmployeeDetails details = (EmployeeDetails) authentication.getPrincipal();
因为身份验证为空。我已经用 @MockUser
注释了测试,但身份验证仍然为空。我如何在控制器方法的参数中模拟身份验证?
我的测试用 @AutoConfigureMockMvc(addFilters = false)
谢谢!
如果您最初有一个用户持久保存在您的数据库中(或者如果您在@PostConstruct 中创建这样的用户),您可以使用@WithUserDetails 注释。
@WithMockUser
这将使用 Authentication 上的 principal is Spring Security 的 User object
虽然 @WithMockUser
是一种非常方便的入门方式,但它可能 并非在所有情况下都有效 。例如,应用程序通常期望 Authentication
主体属于 特定类型 。这样做是为了让应用程序可以将主体称为自定义类型,并减少 Spring 安全性上的耦合。
自定义主体通常由自定义 UserDetailsService
返回,returns 一个同时实现 UserDetails
和自定义类型的对象。对于这种情况,使用自定义 UserDetailsService 创建测试用户很有用。这正是 @WithUserDetails
所做的。
我们可以创建自己的注解,使用@WithSecurityContext 来创建我们想要的任何SecurityContext。例如,我们可以创建一个名为 @WithMockCustomUser 的注解作为 @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)