【问题标题】:MockMVC Integrate test controller with session scoped beanMockMVC 将测试控制器与会话范围 bean 集成
【发布时间】:2015-09-13 17:16:45
【问题描述】:

我正在尝试集成测试 Spring Controller 方法,该方法使用注入到控制器中的 Spring 会话范围 bean。为了让我的测试通过,在我对这个控制器方法进行模拟调用之前,我必须能够访问我的会话 bean 以在其上设置一些值。问题是在我进行调用时创建了一个新的会话 bean,而不是使用我从模拟应用程序上下文中提取的那个。如何让我的控制器使用相同的 UserSession bean?

这是我的测试用例

    @RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration("src/main/webapp")
@ContextConfiguration({"file:src/main/webapp/WEB-INF/applicationContext.xml",
        "file:src/main/webapp/WEB-INF/rest-servlet.xml",
        "file:src/main/webapp/WEB-INF/servlet-context.xml"})
public class RoleControllerIntegrationTest {

    @Autowired
    private WebApplicationContext wac;

    protected MockMvc mockMvc;
    protected MockHttpSession mockSession;

    @BeforeClass
    public static void setupClass(){
        System.setProperty("runtime.environment","TEST");
        System.setProperty("com.example.UseSharedLocal","true");
        System.setProperty("com.example.OverridePath","src\\test\\resources\\properties");
        System.setProperty("JBHSECUREDIR","C:\\ProgramData\\JBHSecure");
    }

    @Before
    public void setup(){
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        mockSession = new MockHttpSession(wac.getServletContext(), UUID.randomUUID().toString());
        mockSession.setAttribute("jbhSecurityUserId", "TESTUSER");
    }

    @Test
    public void testSaveUserRole() throws Exception {

        UserSession userSession = wac.getBean(UserSession.class);
        userSession.setUserType(UserType.EMPLOYEE);
        userSession.setAuthorizationLevel(3);

        Role saveRole = RoleBuilder.buildDefaultRole();
        Gson gson = new Gson();
        String json = gson.toJson(saveRole);

        MvcResult result = this.mockMvc.perform(
                post("/role/save")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(json)
                        .session(mockSession))
                .andExpect(status().isOk())
                .andReturn();

        MockHttpServletResponse response = result.getResponse();

    }

这是我需要测试的控制器方法

    @Resource(name="userSession")
    private UserSession userSession;

    @RequestMapping(method = RequestMethod.POST, value = "/save")
    public @ResponseBody ServiceResponse<Role> saveRole(@RequestBody Role role,HttpSession session){

        if(userSession.isEmployee() && userSession.getAuthorizationLevel() >= 3){
            try {
                RoleDTO savedRole = roleService.saveRole(role,ComFunc.getUserId(session));
                CompanyDTO company = userSession.getCurrentCompany();

它没有通过这一行,因为 UserSession 对象不一样 if(userSession.isEmployee() && userSession.getAuthorizationLevel() >= 3){

这是我的用户会话 bean 的声明。

   @Component("userSession")
   @Scope(value="session",proxyMode= ScopedProxyMode.INTERFACES)
   public class UserSessionImpl implements UserSession, Serializable  {

    private static final long serialVersionUID = 1L;

controlle 和 bean 都是在我的 applicationContext.xml 中使用组件扫描创建的

<context:annotation-config />
    <!-- Activates various annotations to be detected in bean classes -->
    <context:component-scan
        base-package="
            com.example.app.externalusersecurity.bean,
            com.example.app.externalusersecurity.service,
            com.example.app.externalusersecurity.wsc"/>
    <mvc:annotation-driven />

【问题讨论】:

    标签: spring-mvc junit integration-testing stateful-session-bean mockmvc


    【解决方案1】:

    添加如下bean配置,为每个线程添加一个会话上下文

    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
                <entry key="session">
                    <bean class="org.springframework.context.support.SimpleThreadScope"/>
                </entry>
            </map>
        </property>
    </bean>
    

    Java 配置类中的等价物是下面的 bean 声明

    @Bean
      public CustomScopeConfigurer scopeConfigurer() {
        CustomScopeConfigurer configurer = new CustomScopeConfigurer();
        Map<String, Object> workflowScope = new HashMap<String, Object>();
        workflowScope.put("session", new SimpleThreadScope());
        configurer.setScopes(workflowScope);
    
        return configurer;
      }
    

    有关详细信息,请参阅 http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-custom-using

    【讨论】:

      【解决方案2】:

      使用不同的 Bean definition profiles 进行测试和生产对我很有效 - 以下是基于 XML 的设置的样子:

      <beans profile="production">
          <bean id="userSession" class="UserSessionImpl" scope="session" >
              <aop:scoped-proxy/>
          </bean>
      </beans>
      
      <beans profile="test">
          <bean id="userSession" class="UserSessionImpl" >
          </bean>
      </beans>
      

      要为您的测试使用测试配置文件,请将@ActiveProfiles 添加到您的测试类中:

      @RunWith(SpringJUnit4ClassRunner.class)
      @WebAppConfiguration("src/main/webapp")
      @ContextConfiguration({"file:src/main/webapp/WEB-INF/applicationContext.xml",
          "file:src/main/webapp/WEB-INF/rest-servlet.xml",
          "file:src/main/webapp/WEB-INF/servlet-context.xml"})
      @ActiveProfiles(profiles = {"test"})
      public class RoleControllerIntegrationTest {
      [...]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        • 2014-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多