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


@WithUserDetails

虽然 @WithMockUser 是一种非常方便的入门方式,但它可能 并非在所有情况下都有效 。例如,应用程序通常期望 Authentication 主体属于 特定类型 。这样做是为了让应用程序可以将主体称为自定义类型,并减少 Spring 安全性上的耦合。

自定义主体通常由自定义 UserDetailsService 返回,returns 一个同时实现 UserDetails 和自定义类型的对象。对于这种情况,使用自定义 UserDetailsS​​ervice 创建测试用户很有用。这正是 @WithUserDetails 所做的。


@WithSecurityContext

我们可以创建自己的注解,使用@WithSecurityContext 来创建我们想要的任何SecurityContext。例如,我们可以创建一个名为 @WithMockCustomUser 的注解作为 @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)