12月20号例会记录

由于junit的测试脚本编写进入了一个误区,一天的时间都没能解决一个bug,导致进度延后。预计将于明日完成全部工作。

现将bug进行描述:

由于测试使用的项目采用了Struts+Spring,故不能直接采用junit进行测试。(这个算不算是mock测试的内容)

故在网上查找资料后找到了一个Struts2的单元测试包struts-junit-plugin.jar。随后针对该包写代码。

按照网上普遍的做法。编写代码:

    @Test
    public void testShowAllTeacher() throws Exception  {
        showProxy=getActionProxy("/ShowAllTeacher");
        showAction=(TeacherManageAction)showProxy.getAction();
        assertNotNull(showAction);
    }

获取struts的uri,以便进行测试。

结果在获取proxy的这一步不断出错,右下角的提示是java.lang.NullPointerException

第一反应:地址不对。于是将"/ShowAllTeacher" 更改,并作出了各种尝试,包括去掉斜杠,加详细地址,结果都无效。

第二反应:包缺失。查阅资料后,发现似乎要导入spring-mock.jar和sprint-test.jar。(后者这个包似乎在新版本中已经不再使用了)。于是开始找包导包的旅程。。

最终在各大奇怪网站(官网都是maven安装)找齐并导入。遗憾的是错误完全没有消失。。

第三反应:applicationContext.xml位置不对。看到网上有大神说,由于struts默认会读取WEB-INF/文件夹,而junit默认读取src目录。所以将改文件在两个文件都复制了一份,遗憾的是,依然没有解决这个错误。

在以上各大尝试都失败后。不免有些失落。

调账心态后。我发现有些叫报错的地方,可以查看源代码出错的位置。但是需要Struts-core和struts-junit-plugin的源代码。如实我去官网下载了这两个文件的源代码,并导入class,查看了报错函数的出错函数。

之后令人吃惊的事发生了。以下是该函数源代码:

/**
     * Creates an action proxy for a request, and sets parameters of the ActionInvocation to the passed
     * parameters. Make sure to set the request parameters in the protected "request" object before calling this method.
     */
    protected ActionProxy getActionProxy(String uri) {
        request.setRequestURI(uri);  //出错位置
        ActionMapping mapping = getActionMapping(request);
        String namespace = mapping.getNamespace();
        String name = mapping.getName();
        String method = mapping.getMethod();

        Configuration config = configurationManager.getConfiguration();
        ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
                namespace, name, method, new HashMap<String, Object>(), true, false);

        initActionContext(proxy.getInvocation().getInvocationContext());

        // this is normally done in onSetUp(), but we are using Struts internal
        // objects (proxy and action invocation)
        // so we have to hack around so it works
        ServletActionContext.setServletContext(servletContext);
        ServletActionContext.setRequest(request);
        ServletActionContext.setResponse(response);

        return proxy;
    }

该函数在执行第一句话就已经报错了。第一句话是:

request.setRequestURI(uri);

what?request报错?难道是我没有打开服务器的原因吗?于是乎我将工程部署到Tomcat中,并打开服务。确认网站能访问,且各项功能都正常运作。

我再运行单元测试,依然,依然,依然无效。。。报错还是空指针。

于是我又找到request的实体类:MockHttpServletRequest。我想看看这个类的源码时,在网上怎么也找不到。难道这货不是开源的?

正当我快要放弃的时候。无意间查到了这个类是对javax.servlet.http.HttpServletRequest类的mock实现。我又仿佛见到了希望。

说明这两个类再原理上是相似的。这时候我写下测试代码,尝试HttpServletRequest是否能正确创建:

    @Test
    public void testShowAllTeacher() throws Exception  {
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().write("data"); 
    }

结果发现报错是相同的!这我就很兴奋了。关于HttpServletRequest的错误在网上应该能很轻松的找到答案。

果不出所料,一查就查到了问题所在:浏览器在访问网页时会自动创建session对象。而单元测试的时候则不会。

由于session不存在,才导致所有request都空指针。

至此,我终于找到了错误原因,可喜可贺可喜可贺。

但是解决办法?貌似没有。。。。。。。。。。。。。。。。

也需要涉及到mock测试才会有吧。不过这其中收获还是不少的,也不枉我这一天的debug。

参考资料:

https://baike.1688.com/doc/view-d36971790.html

http://fenglingcorp.iteye.com/blog/1197416

http://blog.csdn.net/daijunjieok/article/details/6023632                                   //关键之处

posted on 2017-12-21 15:08  SoftwareTestingHUST  阅读(170)  评论(1编辑  收藏  举报