복붙노트

[SPRING] 왜 Spring MockMvc 결과는 쿠키를 포함하지 않는 것입니까?

SPRING

왜 Spring MockMvc 결과는 쿠키를 포함하지 않는 것입니까?

내 REST API에서 단위 테스트 로그인과 보안을 시도하고 있으므로 실제 요청 시퀀스를 최대한 가깝게하려고합니다.

내 첫 번째 요청은 다음과 같습니다.

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).
    addFilters(springSecurityFilterChain).build();
this.mapper = new ObjectMapper();
....
MvcResult result=mockMvc.perform(get("/login/csrf")).andExpect(status().is(200)).andReturn();
Cookie[] cookies = result.getResponse().getCookies();

(pastebin의 풀 클래스 참조).

나중에 수신 된 CSRF 토큰으로 로그인 할 수 있도록 여기에 쿠키를 가져 오려고하지만 쿠키 배열이 비어 있습니다!

그러나 응용 프로그램을 실행하고 전화를 걸면

curl -i http://localhost:8080/login/csrf

나는 Set-Cookie 헤더를 얻었고 그 쿠키 (그리고 CSRF 토큰)를 나중에 인증에 사용할 수있다.

그래서 질문은 : 어떻게 MockMvc에 쿠키를 돌려 주나요?

해결법

  1. ==============================

    1.MockHttpServletRequest에서 세션 개체를 직접 추출하는 기능을 사용하여 해결 방법을 찾았습니다.

    MockHttpServletRequest에서 세션 개체를 직접 추출하는 기능을 사용하여 해결 방법을 찾았습니다.

    session=(MockHttpSession)result.getRequest().getSession();
    

    나중에 세션을 직접 삽입하십시오.

    req.session(session);
    

    이 솔루션에 만족하지 않는 이유는 mock httpservlet이 실제 서블릿과 다르게 동작한다면, 다른 경우 실제 서블릿과 동일한 동작을하는지 어떻게 확신 할 수 있는가하는 것입니다. 따라서 응용 프로그램 자체를 테스트하지는 않아 잠재적으로 테스트에 차이가 생길 수 있습니다.

  2. ==============================

    2.쿠키로 테스트하기 위해 RestTemplate에서 작업합니다. RestTemplate 쿠키 핸들러

    쿠키로 테스트하기 위해 RestTemplate에서 작업합니다. RestTemplate 쿠키 핸들러

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
    @Import(RestTemplateWithCookies.class)
    public class ApplicationTest {
    
        @LocalServerPort
        private int port;
    
        @Autowired
        private Environment env;
    
        @Autowired
        private RestTemplateWithCookies restTemplate;
    
        @Test
        public void appTest() throws Exception {
            HttpHeaders headers = new HttpHeaders();
            headers.set("Referer", env.getProperty("allowed_referer"));
            HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
            ResponseEntity<String> response = restTemplate.exchange("http://localhost:" + port + "/scan?email=xxx@xxx.com", HttpMethod.GET, entity, String.class);
            assertTrue(response.getStatusCode() == HttpStatus.FOUND);
            HttpCookie c = restTemplate.getCoookies().stream().filter(x -> env.getProperty("server.session.cookie.name").equals(x.getName())).findAny().orElse(null);
            assertTrue(c != null);
    
        }
    
    }
    
  3. ==============================

    3.P.Peter의 답변에 따라 mockMvc에서 수행 된 각 요청 (MockHttpServletRequestBuilder)에 대해 자동으로 세션을 가져오고 되돌릴 코드 조각을 만들었습니다.

    P.Peter의 답변에 따라 mockMvc에서 수행 된 각 요청 (MockHttpServletRequestBuilder)에 대해 자동으로 세션을 가져오고 되돌릴 코드 조각을 만들었습니다.

    @Autowired
    private WebApplicationContext webApplicationContext;
    
    @Autowired
    private Filter springSecurityFilterChain;
    
    @Before
    public void setUp() throws Exception {
        final MockHttpServletRequestBuilder defaultRequestBuilder = get("/dummy-path");
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext)
                .defaultRequest(defaultRequestBuilder)
                .alwaysDo(result -> setSessionBackOnRequestBuilder(defaultRequestBuilder, result.getRequest()))
                .apply(springSecurity(springSecurityFilterChain))
                .build();
    }
    
    private MockHttpServletRequest setSessionBackOnRequestBuilder(final MockHttpServletRequestBuilder requestBuilder,
                                                                 final MockHttpServletRequest request) {
        requestBuilder.session((MockHttpSession) request.getSession());
        return request;
    }
    

    긴 답변 :이 해결책을 확인하십시오. (답은 봄 4입니다) : 봄 3.2 사용자에 로그인하는 방법

  4. from https://stackoverflow.com/questions/26142631/why-does-spring-mockmvc-result-not-contain-a-cookie by cc-by-sa and MIT license