Affects: 5.2.0.RELEASE
When building a WebClient, a helpful method would be to set the session from an existing MockHttpSession, eg:
WebClient webClient = MockMvcWebClientBuilder
.mockMvcSetup( mockMvc )
//.session(mockSession) <-- TODO
.build();
This method could set the required JSESSIONID cookie so that the session is recognized.
Use case:
WebClient requests a page with an iframe that loads its contents from a spring Controller that uses a mocked Session scoped bean. Mocking the session scoped bean only works for the autowired MockHttpSession that is not used in htmlunit's WebClient.
Comment From: cdalexndr
After trying the following workaround
webClient.getCookieManager()
.addCookie( new Cookie( "localhost", "JSESSIONID", session.getId(), "/", 3600, false ) );
, I've noticed that the mocked session is not reused, but a new one is created by HtmlUnitRequestBuilder:
private MockHttpSession httpSession(MockHttpServletRequest request, final String sessionid) {
....
if (session == null) {
session = new HtmlUnitMockHttpSession(request, sessionid);
}
because MockMvcWebConnection doesn't have any sessions associated (field Map
So, for the workaround to work, in MockMvcWebConnection must add method to add a MockHttpSession to the map (public, because class and constr is public) + other utility methods (such as hasSession, getSessions):
public void addSession( MockHttpSession session ) {
sessions.put( session.getId(), session );
}
If the MockMvcWebClientBuilder.session(mockSession) method will be also added, then MockMvcWebConnectionBuilderSupport.createConnection method must use the above newly added method to register the session.
Comment From: bclozel
Sorry for the delay.
I think the current arrangement is by design, as sessions are meant to hold state on the server side and to be created by the server. With this proposal, test code would create a mock session with no state attached, not created by the server.
@Test
void shouldUsePersistentSession() throws Exception {
this.mockMvc = MockMvcBuilders.standaloneSetup(new SessionController()).apply(SharedHttpSessionConfigurer.sharedHttpSession()).build();
WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build();
String sessionId = getResponse(client, "http://localhost/session").getContentAsString();
assertThat(getResponse(client, "http://localhost/session").getContentAsString()).isEqualTo(sessionId);
}
I think in this case the SharedHttpSessionConfigurer
is a better alternative, as you can guarantee that a single session is reused.
I'm declining this issue as a result.