如何与HtmlUnit共享MockMvc会话?

chr*_*ke- 0 spring spring-mvc spring-test htmlunit geb

我正在使用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()
Run Code Online (Sandbox Code Playgroud)

测试:

when:
    via ProtectedPage

then:
    // this uses session A
    at LoginPage

and:
    // this uses session B
    println mvc.perform(get('/test/sessionAttributes')).andReturn().response.contentAsString
Run Code Online (Sandbox Code Playgroud)

Rob*_*nch 5

摘要

我可以问你为什么要在MockMvc中做一些你的工作,还有一些在HtmlUnit中做?它真的不是这样设计的.相反,我建议与HtmlUnit交互以使用会话(就像您的浏览器一样)并验证这些结果.

这不起作用的原因是MockMvc.perform孤立地工作.HtmlUnit集成桥接MockMvc.perform调用以确保它们在浏览器中工作(即跟踪会话).但是,MockMvc.perform封装调用的逻辑是封装的.

MockMvc行为

MockMvc请求隔离工作,默认情况下会在每个请求上使用新会话.例如,以下两个请求对不同的会话进行操作:

// this uses session A
mvc.perform(get("/test"))

// this uses session B
mvc.perform(get("/test"))
Run Code Online (Sandbox Code Playgroud)

为了重用会话,您必须从第一次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));
Run Code Online (Sandbox Code Playgroud)

HtmlUnit支持跟踪MockMvcWebConnection中的会话,并根据JSESSIONID cookie设置适当的会话(类似于您在上面看到的).

为了HttpSessionMockMvc请求中重用HtmlUnit支持,您需要访问原始会话.但是,此逻辑封装在HtmlUnit支持中,因此您无法访问它.

解决方法

我不希望我们将暴露HtmlUnit集成的内部.我也不建议将MockMvcHtmlUnit集成与直接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;
    }
}
Run Code Online (Sandbox Code Playgroud)

下一步是确保您注册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();
Run Code Online (Sandbox Code Playgroud)

现在,如果您需要发出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
Run Code Online (Sandbox Code Playgroud)