spring会话与MockHttpSession不兼容

问题描述 投票:1回答:1

当我尝试集成spring会话时,以下测试失败。

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();
    }
}

经过一些调试后,我发现可能是因为我无法获得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);

目前,我使用@ConditionalProperties为测试禁用了spring会话。欢迎任何更好的主意。

spring-security spring-test spring-session spring-test-mvc
1个回答
0
投票

这与您在测试中正确设置mockMvc对象有关。

为简洁起见,我假设您可以在项目中使用@SpringBootTest注释。下面的代码显示了如何将与spring-session相关的类正确连接到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---------------------------------

}

© www.soinside.com 2019 - 2024. All rights reserved.