问题
I developed some JUnit tests that extend org.apache.struts2.StrutsTestCase. I used the tutorial on struts.apache.org as my starting point.
Everything was working fine until I modified my simple web application to use Tiles. I have Tiles working fine in the app but now my Action test cases have stopped working.
I'm getting NullPointerException at org.apache.struts2.views.tiles.TilesResult.doExecute when I run the following line of code:
ActionProxy proxy = getActionProxy("/displaytag.action");
The log shows the Struts 2 Action is executing succesfully until it tries to hand it off to TilesResult.doExecute.
I suspect it is because the tests run outside of the container and the tiles.xml is only referenced in the web.xml and therefore my StrutsTestCase tests don't know where to find the definitions in tiles.xml.
Is this making sense?
I'm using Struts 2.2.1.1 and the tiles related jars (v. 2.0.6) included in the Struts distribution.
I'll include a code snippet from my StrutsTestCase but please note everything runs successfully when I run the app from the browser in Tomcat, it only fails when I run the StrutsTestCase outside of Tomcat. And the test cases ran successfully before I added 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);
}
}
Partial stack trace:
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)
Lastly, can anyone explain what the deal is with StrutsTestCase? There's a tutorial page for using it with Struts 2 on struts.apache.org but the SourceForge page for it hasn't been updated since Struts 1.3 Also, what's the difference between StrutsTestCase and MockStrutsTestCase
回答1:
I imagine you're initialising tiles with a listener:
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
You need to initialise that Listener in your tests. I found a few others with the same issue [1]. The code below is in your class that extends StrutsSpringTestCase. You need to override the setupBeforeInitDispatcher. In the code snippet below, the override sets the applicationContext attribute (also needed if you're using spring) and initialises Tiles (inside the if(tilesApplication) segment, where tilesApplication is a boolean so you can toggle this code on an off based on your whether or not your application runs with tiles ):
/** 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] See http://depressedprogrammer.wordpress.com/2007/06/18/unit-testing-struts-2-actions-spring-junit/
回答2:
It is trying to display the jsp page. So disable by adding ExecuteResult(false) in the code.
So, add the below line
proxy.setExecuteResult(false);
before proxy.execute()
来源:https://stackoverflow.com/questions/5823709/npe-in-strutstestcase-after-enabling-tiles