如何在单元测试期间为Thymeleaf模板传递身份验证
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在单元测试期间为Thymeleaf模板传递身份验证相关的知识,希望对你有一定的参考价值。
我正在使用Spring Boot 2.0.8.RELEASE。我有一个控制器,它具有以下方法构造
@PostMapping(value = "/profile/change-password", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public Mono<String> changePasswordSubmit(Authentication authentication, @RequestBody MultiValueMap<String, String> formData) {
我的单元测试看起来像:
@RunWith(SpringRunner.class)
@WebFluxTest(controllers = ChangePasswordController.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Import({ThymeleafAutoConfiguration.class, SpringSecurityContextUtils.class})
@WithMockUser(username = "test", password = "password")
public class ChangePasswordControllerTest {
@Autowired
WebTestClient webTestClient;
@MockBean
SpringUserDetailsRepository userDetailsRepository;
@Autowired
ChangePasswordController controller;
@MockBean
Authentication authentication;
@Test
public void addNewEntrySubmit() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.put("password1", Collections.singletonList("password"));
formData.put("password2", Collections.singletonList("password"));
webTestClient.post().uri("/profile/change-password").contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData(formData)).exchange().expectStatus().isSeeOther().expectHeader().valueEquals(HttpHeaders.LOCATION, "/page/1");
// verify(userDetailsRepository).updatePassword(captor.capture(), captor.capture());
doNothing().when(userDetailsRepository).updatePassword(any(), any());
}
}
我的问题是,当我运行测试时,控制器上的Authentication值为null。我试图添加安全上下文,但遇到了正确的问题。我该如何解决
更新:链接到示例存储库:https://github.com/dmbeer/thymeleaf-spring-security-test
答案
在Spring Boot 5.1.x之前,您需要手动添加Spring Security过滤器配置:
WebTestClient webTestClient = WebTestClient
.bindToController(new ChangedPasswordController())
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity())
.configureClient()
.build();
在5.1.x中,@WebFluxTest
会自动添加这些调用,因此您不必这样做。
你可以在the Spring Security repo中看到它的一个例子。
另一答案
所以在@jzheaux和相关文档的帮助下,以及webflux https://docs.spring.io/spring-security/site/docs/5.0.11.RELEASE/reference/html/test-webflux.html的指南
我的单元测试如下所示:
@RunWith(SpringRunner.class)
@Import({ThymeleafAutoConfiguration.class})
@WebFluxTest(controllers = ChangePasswordController.class)
@WithMockUser(username = "test", authorities = {"ROLE_ADMIN"})
@ContextConfiguration
public class ChangePasswordControllerTest {
@Autowired
ApplicationContext context;
private WebTestClient webTestClient;
@MockBean
SpringUserDetailsRepository userDetailsRepository;
@Captor
private ArgumentCaptor<String> captor;
@Before
public void setUp() throws Exception {
webTestClient = WebTestClient.bindToApplicationContext(context)
.webFilter(new SecurityContextServerWebExchangeWebFilter())
.apply(springSecurity())
.configureClient()
.build();
}
@Test
public void getChangePasswordPageTest() {
EntityExchangeResult<String> result = webTestClient
.mutateWith(csrf())
.get().uri("/profile/change-password")
.exchange()
.expectStatus().isOk()
.expectBody(String.class).returnResult();
assertThat(result.getResponseBody(), stringContainsInOrder(Arrays.asList("<title>Change Password</title>",
"<input type="password" class="form-control" id="password1" name="password1">")));
}
@Test
public void addNewEntrySubmit() {
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.put("password1", Collections.singletonList("password"));
formData.put("password2", Collections.singletonList("password"));
given(userDetailsRepository.updatePassword(any(), any())).willReturn(Mono.empty());
webTestClient.mutateWith(csrf()).post().uri("/profile/change-password").contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(BodyInserters.fromFormData(formData)).exchange().expectStatus().isSeeOther().expectHeader().valueEquals(HttpHeaders.LOCATION, "/page/1");
verify(userDetailsRepository).updatePassword(captor.capture(), captor.capture());
// doNothing().when(userDetailsRepository).updatePassword(any(), any());
}
}```
以上是关于如何在单元测试期间为Thymeleaf模板传递身份验证的主要内容,如果未能解决你的问题,请参考以下文章
如何对使用 thymeleaf 的安全控制器进行单元测试(不获取 TemplateProcessingException)?