3

The following test fails when I try to integrate spring session.

class WeChatOAuth2AuthenticationFilterTest extends AbstractWebMvcTest {

    @Test
    void it_should_redirect_user_to_origin_uri_when_wechat_oauth_is_finished() throws Exception {

        String code = "codeToExchangeWeChatUserAccessToken"
        String plainUrl = "http://www.example.com/index.html?a=b#/route"
        String state = Base64.getUrlEncoder().encodeToString(plainUrl.getBytes("UTF-8"))
        WxMpOAuth2AccessToken accessToken = new WeChatUserOAuth2AccessTokenFixture().buildToken()

        given(wxMpService.oauth2getAccessToken(code))
                .willReturn(accessToken)

        this.mockMvc.perform(get("/wechat/oauth/token")
                .param("state", state) 
                .param("code", code))
                .andDo(print())
                .andExpect(status().is3xxRedirection())
                .andExpect(redirectedUrl(plainUrl)) 
                .andExpect(authenticated()) 
                // throws Authentication should not be null
    }   
}

@Configuration
@EnableSpringHttpSession
public class HttpSessionConfig {

    @Bean
    protected SessionRepository sessionRepository() {
        return new MapSessionRepository();
    }
}

After some debugging, I find out that it is probably due to I cannot get HttpSession

// org.springframework.security.web.context.HttpSessionSecurityContextRepository
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
        HttpServletRequest request = requestResponseHolder.getRequest();
        HttpServletResponse response = requestResponseHolder.getResponse();
        HttpSession httpSession = request.getSession(false); 
        //returns null with spring-session, 
        //returns a MockHttpSession instance without spring-session

        SecurityContext context = readSecurityContextFromSession(httpSession);

Currently, I make the spring session disabled for the tests with @ConditionalProperties. Any better idea is welcome.

fap
  • 663
  • 1
  • 5
  • 14
Yugang Zhou
  • 7,123
  • 6
  • 32
  • 60

1 Answers1

2

This is related to correct setup of you mockMvc object in your test.

For brevity, I assume you can use @SpringBootTest annotation in your project. The codes below shows how you could properly wire in spring-session related classes into your mockMvc.

@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class ExampleControllerV2SpringSessionTest {

@Autowired
private WebApplicationContext wac;

@Autowired
private SessionRepository sessionRepository;

@Autowired
private SessionRepositoryFilter sessionRepositoryFilter;

//this is needed to test spring-session specific features
private MockMvc mockMvcWithSpringSession;

@Before
public void setup() throws URISyntaxException {

    this.mockMvcWithSpringSession = MockMvcBuilders
       .webAppContextSetup(wac)
       .addFilter(sessionRepositoryFilter)
       .build();
}


//------------------------- BEGIN: Test cases with Spring-session---------------------------------

@Test
public void getANewSpringSession(String requestBody) throws Exception {
    MvcResult result = mockMvcWithSpringSession.perform(
            get("/v1/sampleendpoint")                    .header("YOUR_HEADER_NAME", "YOUR_HEADER_VALUE")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content("YOUR_SAMPLE_JSON_BODY"))
            .andExpect(status().isOk())
            .andExpect(header().string("x-auth-token", notNullValue()))
            .andReturn();

    String xAuthToken = result.getResponse().getHeader(AuthenticationControllerV2.Params.SESSION_KEY);
    MapSession curSession = (MapSession) sessionRepository.getSession(xAuthToken);
    Assert.assertNotNull(curSession);
}

//------------------------- END: Test cases with Spring-session---------------------------------

}

imarchuang
  • 467
  • 7
  • 17