使用会话范围的bean依赖项

时间:2015-08-06 15:25:16

标签: java spring-mvc

我有一个问题,我无法解决。我在互联网和Stackoverflow上搜索过但无法找到解决问题的方法。

我想测试一个Spring MVC Handler拦截器。此拦截器具有“会话”范围bean作为依赖项。

我尽可能地减少了代码。这是代码:

src部分:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = { "..." })
public class SpringMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry interceptorRegistry) {
        interceptorRegistry.addInterceptor(initializeUserLanguageHandler());
    }

    @Bean
    public InitializeUserLanguageHandler initializeUserLanguageHandler() {
        return new InitializeUserLanguageHandler();
    }

    @Bean
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public SessionBean sessionBean() {
        return new SessionBean();
    }
}


@Component
public class InitializeUserLanguageHandler extends AbstractHandlerInterceptor {

    @Autowired
    private SessionBean sessionBean;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (sessionBean.getLanguage() == null) {
            sessionBean.setLanguage(getUserLanguage());
        }

        return true;
    }
}

测试部分:

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringMvcConfiguration.class)
public class BaseSpringMvcIntegrationTest {

    @Resource
    protected WebApplicationContext webApplicationContext;

    protected MockMvc mockMvc;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
}

public class InitializeUserLanguageHandlerTest extends BaseSpringMvcIntegrationTest {

    @Autowired
    private SessionBean sessionBean;

    @Autowired
    private MockHttpSession mockHttpSession;

    @Test
    public void testLanguageIsInitializedOnlyOnce() throws Exception {
        MockHttpSession mocksession = new MockHttpSession();

        // It is null, this is because the interceptor has not been called yet
        assertEquals(null, sessionBean.getLanguage());

        // This line will call the interceptor and set language to "nl"
        mockMvc.perform(get("/").session(mocksession).principal(getUser("nl")));

        // It is null, but I expect it to be "nl" 
        assertEquals(null, sessionBean.getLanguage()); 

        // Let's try again     
        mockMvc.perform(get("/").session(mocksession).principal(getUser("fr")));

        // It is null, but I expect it to be "nl" 
        assertEquals(null, sessionBean.getLanguage());
    }
}

你可以在测试类“InitializeUserLanguageHandlerTest”中看到我有一些断言。

我第一次打电话:

mockMvc.perform(get("/").session(mocksession).principal(getUser()));

执行拦截器中的代码并将语言设置为“nl”。因此,在我的测试中,我希望sessionBean.getLanguage()会返回“nl”,但事实并非如此。我不明白为什么。

所以我再次调用perform,再次执行拦截器代码,并调用sessionBean.getLanguage()返回“nl”。

似乎我有两个SessionBean实例,一个在我的测试中,另一个在源中。但是当我在调试模式下查看Eclipse中的SessionBean变量时,它们具有相同的ID。

如果我将“会话”范围更改为“应用程序”范围,则表明它正常工作。

有人能帮助我吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

这是解决问题的一种方法,但不确定它是最好的。

@ContextConfiguration(classes = {SpringMvcConfiguration.class, InitializeUserLanguageHandlerTest.BeanConfig.class})
public class InitializeUserLanguageHandlerTest extends BaseSpringMvcIntegrationTest {

    @Configuration
    public static class BeanConfig {
        @Bean(name = "sessionBean")
        public SessionBean sessionBean() {
            return new SessionBean();
        }
    }
    ...
}