wiki:demo_05

Version 5 (modified by chenyang, 14 years ago) (diff)

--

单元测试应用示例——测试Servlet类

Servlet对象由Web容器创建,它依赖HttpServletRequest,HttpServletResponse?,ServletConfig等对象,很难使用Junit进行单元测试.但如果借助Spring测试框架的话,就比较容易了.
Spring测试框架提供了MockHttpServletRequest,MockHttpServletResponse?MockServletConfig?,等对象,可以很方便地模拟Servlet依赖的环境。

AdRegistedServlet在用户在游戏的注册引导页完成注册后,将用户信息统计到数据库.

/**
 * 
 * @author ChenYang
 * Date: 2011-12-30
 */
public class AdRegistedServlet extends HttpServlet {
        
        private static Log log = LogFactory.getLog(AdRegistedServlet.class);
        
        
        private ApplicationContext applicationContext = null;

        public void setApplicationContext(ApplicationContext applicationContext) {
                this.applicationContext = applicationContext;
        }

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse res)
                        throws ServletException, IOException {
                doPost(req,res);
        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse res)
                        throws ServletException, IOException {
                
                String accountId = req.getParameter("accountId");
                
                String returnUrl = req.getParameter("return");
                
                if(StringUtils.isBlank(accountId)){
                        return;
                }
                
                Passport passport = (Passport) applicationContext.getBean("passport");
                try {
                        Session realmSession = passport.login(req, res);
                        log.info(realmSession.getAccountId());
                } catch (LoginException e) {
                        log.error(e.getMessage());
                }
                
                String srcid = req.getParameter("srcid");
                
                if(StringUtils.isBlank(srcid)){
                        res.sendRedirect(returnUrl);
                }else{
                        
                        AdTypeDAO adTypeDAO = (AdTypeDAO) applicationContext.getBean("adTypeDAO");
                        AdType adType = adTypeDAO.find(Long.valueOf(srcid));
                        
                        if(adType == null){
                                log.info("非法的推广来源:"+srcid);
                                res.sendRedirect(returnUrl);
                                return;
                        }
                        
                        String ip = IpUtils.getIp(req);
                        AdRequest ad_request = new AdRequest();
                        ad_request.setSrcId(StringUtils.isBlank(srcid) ? -1 : Long.valueOf(srcid));
                        ad_request.setSrc(adType == null ? "" : adType.getSrc());
                        
                        ad_request.setIp(ip);
                        
                        String referer = req.getHeader("Referer");
                        
                        if(referer == null){
                                return;
                        }
                
                        long gameid = AdRequestUtils.refererToGameId(referer);
                        
                        if(gameid == 0){
                                log.info("未配置游戏id的请求来源:"+referer);
                                res.sendRedirect(returnUrl);
                                return;
                        }
                        
                        ad_request.setGameid(gameid);
                        
                        ad_request.setUserid(Long.valueOf(accountId));
                        Date now = new Date();
                        ad_request.setCreateAt(now);
                        ad_request.setStatus(AdRequestUtils.REGISTED_STATUS);
                        ad_request.setReferer(req.getParameter("referer"));
                
                        AdRequestDAO adRequestDAO = (AdRequestDAO) applicationContext.getBean("adRequestDAO");
                        adRequestDAO.createAdRequest(ad_request);
                        res.sendRedirect(returnUrl);
                }
                
        }

        @Override
        public void init(ServletConfig config) throws ServletException {
                if(applicationContext == null){
                        ServletContext ctx = config.getServletContext();
                        this.applicationContext = WebApplicationContextUtils.getWebApplicationContext(ctx);
                }
        }
        
        
        
}

要测试doPost()方法的话,首先要准备applicationContext,我们可以通过继承AbstractTransactionalJUnit4SpringContextTests,以获得ApplicationContext
然后,我们要模拟HttpServletRequest,HttpServletResponse?

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class AdRegistedServletTest extends AbstractTransactionalJUnit4SpringContextTests{
        
        @Before
        public void init(){
                 Env env = EnvUtils.getEnv();
                 MockHttpServletRequest request = new MockHttpServletRequest();
                 request.addHeader("X-Forwarded-For", "192.168.20.92");
                 request.addHeader("X-Real-IP", "192.168.20.92");
                 request.setRemoteAddr("192.168.20.92");
                 
                 env.setRequest(request);
        }
        
        @After
        public void destory(){
                EnvUtils.removeEnv();
        }
        
        @Autowired
    CacheClient cacheClient;
        
        @Autowired
        private AdTypeDAO adTypeDAO;
        
        /**
         * 测试正常流程
         * @throws Exception
         */
        @Test
        public void doPost() throws Exception {
                
                final AdRegistedServlet adRegistedServlet = new AdRegistedServlet();
                adRegistedServlet.setApplicationContext(applicationContext);

                //模拟ServletConfig
                MockServletConfig config = new MockServletConfig();
                adRegistedServlet.init(config);
                
                //模拟HttpServletRequest
                final MockHttpServletRequest request = new MockHttpServletRequest();
                request.addHeader("Referer", "http://g2.pcgames.com.cn/popularize/sxd_register.jsp");
                request.addHeader("X-Forwarded-For", "192.168.20.92");
                request.addHeader("X-Real-IP", "192.168.20.92");
                request.setRemoteAddr("192.168.20.92");
                
                AdType adType = new AdType();
                adType.setSrc("wltg");
                
                long srcid = adTypeDAO.create(adType);
                
                request.addParameter("srcid", ""+srcid);
                request.addParameter("accountId", "393648562");
                request.addParameter("referer", "http://www.sina.com.cn");
                request.addParameter("return", "http://g2.pcgames.com.cn");
                
                //模拟HttpServletResponse
                final MockHttpServletResponse response = new MockHttpServletResponse();
                
                Mockery ctx = new Mockery();
                final EnvInterface env = ctx.mock(EnvInterface.class);
                request.setAttribute("env", env);
                
                ctx.checking(new Expectations(){
                        {
                                one(env).getRoot();
                                will(returnValue("http://g2.pcgames.com.cn"));
                        }
                });
                
                adRegistedServlet.doPost(request, response);
                
                AdRequestDAO adRequestDAO = (AdRequestDAO) applicationContext.getBean("adRequestDAO");
                List<AdRequest> list = adRequestDAO.query("SELECT * FROM ad_request WHERE userid = 393648562 AND ip = '192.168.20.92' AND srcid = "+srcid);
                
                //断言doPost()后,与我们期望的结果一致
                Assert.assertEquals(1,list.size());
                
        }
 ..................

}