启用Tiles后,StrutsTestCase中的NPE

时间:2011-04-28 19:07:21

标签: junit struts2 tiles

我开发了一些扩展org.apache.struts2.StrutsTestCase的JUnit测试。我使用struts.apache.org上的tutorial作为我的起点。

在修改我的简单Web应用程序以使用Tiles之前,一切正常。我的Tiles在应用程序中工作正常,但现在我的Action测试用例已停止工作。

当我运行以下代码行时,我在org.apache.struts2.views.tiles.TilesResult.doExecute收到NullPointerException:

ActionProxy proxy = getActionProxy("/displaytag.action");

日志显示Struts 2 Action正在成功执行,直到它尝试将其移交给TilesResult.doExecute。

我怀疑是因为测试在容器外部运行而且tiles.xml仅在web.xml中引用,因此我的StrutsTestCase测试不知道在tiles.xml中找到定义的位置。

这有意义吗?

我正在使用Struts 2.2.1.1和Struts发行版中包含的与tile相关的jar(v.2.0.6)。

我将包含StrutsTestCase中的代码片段,但请注意当我从Tomcat中的浏览器运行应用程序时,所有内容都成功运行,只有当我在Tomcat之外运行StrutsTestCase时它才会失败。在添加Tiles之前,测试用例已成功运行。

public class TagActionTest extends StrutsTestCase {

static Logger logger = Logger.getLogger(TagActionTest.class);

public void testCreateTagFail() throws Exception {
    logger.debug("Entering testCreateTagFail()");

    try {
        request.setParameter("name", "");

        ActionProxy proxy = getActionProxy("/createtag.action");

        TagAction tagAction = (TagAction) proxy.getAction();

        proxy.execute();

        assertTrue("Problem There were no errors present in fieldErrors but there should have been one error present", tagAction.getFieldErrors().size() == 1);
        assertTrue("Problem field 'name' not present in fieldErrors but it should have been",
                tagAction.getFieldErrors().containsKey("name") );
    } catch (Exception e) {
        logger.debug("Error running testCreateTagFail()");
        e.printStackTrace();

        assertTrue("Error running testCreateTagFail()", false);
    }
}

部分堆栈跟踪:

java.lang.NullPointerException
at org.apache.struts2.views.tiles.TilesResult.doExecute(TilesResult.java:105)
at org.apache.struts2.dispatcher.StrutsResultSupport.execute(StrutsResultSupport.java:186)
at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:373)

最后,有人可以解释StrutsTestCase的交易是什么吗?在Struts.apache.org上有一个与Struts 2一起使用的教程页面,但是自Struts 1.3以来SourceForge page for it还没有更新。另外,StrutsTestCase和MockStrutsTestCase之间有什么区别

2 个答案:

答案 0 :(得分:3)

我想你正在用听众初始化瓷砖:

<listener>
    <listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>

您需要在测试中初始化该Listener。我发现其他一些人有同样的问题[1]。 下面的代码在您的类中扩展StrutsSpringTestCase。您需要覆盖setupBeforeInitDispatcher。在下面的代码片段中,覆盖设置applicationContext属性(如果你使用spring也需要)并初始化Tiles(在if(tilesApplication)段内,其中tilesApplication是一个布尔值,所以你可以在关闭的基础上切换这个代码)你的应用程序是否与tile一起运行):

    /** Overrides the previous in order to skip applicationContext assignment: context is @autowired
 * @see org.apache.struts2.StrutsSpringTestCase#setupBeforeInitDispatcher()
 **/
@Override
protected void setupBeforeInitDispatcher() throws Exception {
    //init context

    servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext);

    if(tilesApplication){
        servletContext.addInitParameter(BasicTilesContainer.DEFINITIONS_CONFIG, "WEB-INF/tiles.xml");
        final StrutsTilesListener tilesListener = new StrutsTilesListener();
        final ServletContextEvent event = new ServletContextEvent(servletContext);
        tilesListener.contextInitialized(event);
    }

}

[1]见http://depressedprogrammer.wordpress.com/2007/06/18/unit-testing-struts-2-actions-spring-junit/

答案 1 :(得分:1)

正在尝试显示jsp页面。因此,通过在代码中添加ExecuteResult(false)来禁用。

所以,添加以下行

proxy.setExecuteResult(false); 

之前proxy.execute()