Unit Testing RestController with SpringSecurity

0

Cześć,

Piszę w sprawie problemu z testami dla prostej aplikacji na SpringBoot ze Spring security:

Oto test:

package pl.group7.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import pl.group7.DummyObjects;
import pl.group7.model.User;
import pl.group7.service.UserService;

import static org.mockito.BDDMockito.given;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

/**
 * Created by allst on 05.05.2017.
 */
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {

    @Autowired
    WebApplicationContext webContext;
    @MockBean
    UserService userService;
    MockMvc mockMvc;

    private User user = DummyObjects.getDummyUser();

    public static String asJsonString(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static User getObjectFromJson(final String json){
        try{
            return new ObjectMapper().readValue(json, User.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Before
    @WithMockUser(username = "admin",authorities = {"SU","ADMIN"})
    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders
                .webAppContextSetup(webContext)
                .apply(springSecurity())
                .build();
    }

    @Test
    @WithMockUser(username = "admin",authorities = {"SU","ADMIN"})
    public void shouldAddUser() throws Exception {
        given(this.userService.save(user)).willReturn(user);
        mockMvc.perform(post("/user")
                        .content(asJsonString(user))
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON)
                        .with(csrf().asHeader()))
                .andExpect(status().is(200));
    }

    @Test
    @WithMockUser(username = "admin",authorities = {"SU","ADMIN"})
    public void removeUser() throws Exception {
        mockMvc.perform(delete("/user/1")
                        .with(csrf().asHeader()))
                .andExpect(status().is(200));
    }

A to konfiguracja security:

package pl.group7.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfFilter;
import pl.group7.security.CsrfTokenResponseHeaderBindingFilter;
import pl.group7.security.RESTAuthenticationFailureHandler;
import pl.group7.security.RESTAuthenticationSuccessHandler;
import pl.group7.service.CustomUserDetailsService;

/**
 * created by : Dominik 12.03.2017
 * */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CustomUserDetailsService userDetailsService;
    @Autowired
    private RESTAuthenticationFailureHandler authenticationFailureHandler;
    @Autowired
    private RESTAuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("user").authorities("MAKE_ORDER");
        auth.inMemoryAuthentication().withUser("admin").password("admin").authorities("SU");
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/api/**").hasAuthority("SU")
                .antMatchers(HttpMethod.POST, "/api/user").permitAll()
                .antMatchers(HttpMethod.PUT, "/api/user").authenticated()
                .antMatchers(HttpMethod.DELETE,"api/user/**").authenticated()
                .and().formLogin().successHandler(authenticationSuccessHandler)
                .and().formLogin().failureHandler(authenticationFailureHandler);
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                .and().addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);
//        http.csrf().disable();
    }

}

I przy odpalaniu testu dostaje kod http 404. Wzorowałem się na http://docs.spring.io/spring-security/site/docs/current/reference/html/test-method.html .
Macie jakieś pomysły dotyczące dlaczego nie mogę się dostać do kontrollera skoro daje mu csrf jak i przekazuje ze jestem zalogowany jako admin z odpowiednimi prawami.

pozdrawiam

1

Widze w security reguły typu /api/user a operacje robisz na /user bez api z przodu, więc raczej nic dziwnego ze 404 NOT_FOUND

0

Nice Explanation you can also fine some important Spring and Spring Boot Tutorials.

1 użytkowników online, w tym zalogowanych: 0, gości: 1