我正在使用Spring Test MVC HtmlUnit和Geb来为我的Spring MVC应用程序驱动功能测试。我想检查在交互过程中是否正确保存了一些会话变量。我尝试创建一个测试控制器来返回这些变量,但是HtmlUnit和mvc.perform()
正在使用不同的会话。有没有办法在它们之间使用单个共享会话?
驱动程序设置:
MockMvc mvc = MockMvcBuilders.webAppContextSetup(ctx)
.apply(SecurityMockMvcConfigurers.springSecurity())
.build()
HtmlUnitDriver driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(mvc).javascriptEnabled(true).build()
试验:
when:
via ProtectedPage
then:
// this uses session A
at LoginPage
and:
// this uses session B
println mvc.perform(get('/test/sessionAttributes')).andReturn().response.contentAsString
答案 0 :(得分:5)
我可以问你为什么要在MockMvc中做一些你的工作,还有一些在HtmlUnit中做?它真的不是这样设计的。相反,我建议与HtmlUnit进行交互以使用会话(就像您的浏览器一样)并验证这些结果。
这不起作用的原因是MockMvc.perform
孤立地工作。 HtmlUnit集成桥接MockMvc.perform
调用,以确保它们在浏览器中工作(即跟踪会话)。但是,封装MockMvc.perform
调用的逻辑是封装的。
MockMvc请求隔离工作,默认情况下会在每个请求上使用新会话。例如,以下两个请求对不同的会话进行操作:
// this uses session A
mvc.perform(get("/test"))
// this uses session B
mvc.perform(get("/test"))
为了重用会话,您必须从第一个MockMvc.perform
调用获取会话,并在第MockMvc.perform
次调用时设置它。例如:
MvcResult mvcResult = mvc
.perform(get("/a"))
.andReturn();
// reuse the previous session
MockHttpSession session = (MockHttpSession) mvcResult
.getRequest().getSession();
mvc.perform(get("/b").session(session));
HtmlUnit支持跟踪MockMvcWebConnection中的会话,并根据JSESSIONID cookie设置适当的会话(类似于您在上面看到的)。
为了在HttpSession
请求中重用HtmlUnit支持中的MockMvc
,您需要访问原始会话。但是,此逻辑封装在HtmlUnit支持中,因此您无法访问它。
我不希望我们公开HtmlUnit集成的内部。我也不建议将MockMvc
HtmlUnit集成与直接MockMvc
用法混合和匹配。但是,您可以解决此问题。
第一步是创建一个跟踪上一个会话的ResultHandler
。
public class SessionTracking implements ResultHandler {
private MockHttpSession lastSession;
@Override
public void handle(MvcResult result) throws Exception {
lastSession = (MockHttpSession) result.getRequest().getSession(false);
}
public MockHttpSession getLastSession() {
return lastSession;
}
}
下一步是确保您在SessionTracking
个实例中注册MockMvc
。
SessionTracking sessions = new SessionTracking();
MockMvc mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(SecurityMockMvcConfigurers.springSecurity())
// ADD THIS
.alwaysDo(sessions)
.build();
HtmlUnitDriver driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(mvc)
.build();
现在,如果您需要发出MockMvc
请求,则可以使用SessionTracking
对象访问上一个会话。
when:
via ProtectedPage
then:
// this uses session A
at LoginPage
and:
// this uses session A
println mvc.perform(get('/test/sessionAttributes').session(sessions.lastSession).andReturn().response.contentAsString