2014-10-01 130 views
11

我想在我的REST API中单元测试登录和安全性,所以我尽量模拟真实请求序列。为什么Spring MockMvc结果不包含cookie?

我的第一个要求是:

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满级)。

我尝试在此处获取cookie以便能够稍后使用收到的CSRF令牌登录,但cookies数组为空!

但是,如果我跑我的应用程序,并调用

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

我找回一个Set-Cookie头,并且可以使用该Cookie(和CSRF令牌)之后进行身份验证。

所以问题是:我如何让MockMvc返回一个cookie给我?

+1

你怎么设置你的'mockMvc'? – 2014-10-01 14:28:22

+0

@SotiriosDelimanolis我在问题中编辑了我的代码以表明这一点。当我获得时间时,我会把测试班的相关位放在这里或一个pastebin。 – 2014-10-01 15:48:58

+0

我的测试课的相关部分位于pastebin:http://pastebin.com/LiNeRFT0 – 2014-10-02 12:38:02

回答

9

我已经找到了解决方法,使用直接从MockHttpServletRequest提取会话对象的能力:

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

后来直接插入了会议:

req.session(session); 

为什么我不能高兴的理由这个解决方案是,如果模拟httpservlet在这方面的行为与真正的servlet不同,我怎么能确定它在其他情况下的行为与真实的servlet是否相同。所以我没有测试应用程序本身,这可能会在测试中留下空白。

0

我使用RestTemplate与Cookie进行测试。 RestTemplate cookies handler

@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 + "/[email protected]", 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); 

    } 

} 
0

基于P.Péter的回答一个使这个代码片段,它会得到自动放回会话(MockHttpServletRequestBuilder)上mockMvc执行的每个请求。

@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):How to login a user with spring 3.2 new mvc testing

相关问题