Как пройти проверку подлинности для шаблона Thymeleasf во время модульного теста - PullRequest
0 голосов
/ 26 марта 2019

Я использую 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());
    }
}

Моя проблема в том, что когда я запускаю тест, значение Аутентификации на контроллере равно нулю. Я попытался добавить контекст безопасности, но у меня возникают проблемы с его правильной настройкой. Как мне это исправить

Обновление: Ссылка на пример репозитория: https://github.com/dmbeer/thymeleaf-spring-security-test

Ответы [ 2 ]

0 голосов
/ 30 марта 2019

Итак, после помощи @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());
    }
}```
0 голосов
/ 28 марта 2019

Перед Spring Boot 5.1.x необходимо вручную добавить конфигурацию фильтра Spring Security:

WebTestClient webTestClient = WebTestClient
        .bindToController(new ChangedPasswordController())
        .webFilter(new SecurityContextServerWebExchangeWebFilter())
        .apply(springSecurity())
        .configureClient()
        .build();

В 5.1.x, @WebFluxTest добавляет эти вызовы автоматически, поэтому вам не нужно.

Пример этого можно увидеть в репозитории Spring Security .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...