NPE в StrutsTestCase после включения плиток

#junit #struts2 #tiles

#юнит #struts2 #плитки #junit

Вопрос:

Я разработал несколько тестов JUnit, которые расширяют org.apache.struts2.StrutsTestCase. Я использовал руководство по struts.apache.org в качестве отправной точки.

Все работало нормально, пока я не изменил свое простое веб-приложение для использования Tiles. У меня в приложении Tiles работают нормально, но теперь мои тестовые примеры действий перестали работать.

Я получаю исключение NullPointerException в org.apache.struts2.views.tiles.TilesResult.Выполняется при запуске следующей строки кода:

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

Журнал показывает, что действие Struts 2 выполняется успешно до тех пор, пока оно не попытается передать его TilesResult.doExecute.

Я подозреваю, что это потому, что тесты выполняются вне контейнера и tiles.xml упоминается только в web.xml и поэтому мои тесты StrutsTestCase не знают, где найти определения в tiles.xml .

Есть ли в этом смысл?

Я использую Struts 2.2.1.1 и связанные с плиткой jar (версия 2.0.6), включенные в дистрибутив Struts.

Я включу фрагмент кода из моего StrutsTestCase, но, пожалуйста, обратите внимание, что все выполняется успешно, когда я запускаю приложение из браузера в Tomcat, сбой происходит только при запуске StrutsTestCase за пределами Tomcat. И тестовые примеры успешно выполнялись до того, как я добавил плитки.

 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 есть страница руководства по его использованию с Struts 2.org но страница SourceForge для нее не обновлялась со времен Struts 1.3 Кроме того, в чем разница между StrutsTestCase и MockStrutsTestCase

Комментарии:

1. Я наткнулся на ту же проблему. Тебе удалось недооценить и решить проблему, Джастин?

2. @wild_oscar, к сожалению, нет. удачи

3. @Justin нашел какое-либо решение?

Ответ №1:

Я полагаю, вы инициализируете tiles с помощью прослушивателя:

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

Вам необходимо инициализировать этот прослушиватель в ваших тестах. Я нашел несколько других с такой же проблемой [1].
Приведенный ниже код находится в вашем классе, который расширяет StrutsSpringTestCase. Вам необходимо переопределить setupBeforeInitDispatcher. В приведенном ниже фрагменте кода переопределение устанавливает атрибут ApplicationContext (также необходимый, если вы используете spring) и инициализирует Tiles (внутри сегмента if(tilesApplication), где tilesApplication является логическим значением, поэтому вы можете переключить этот код на off в зависимости от того, выполняется ли ваше приложение с 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] См http://depressedprogrammer.wordpress.com/2007/06/18/unit-testing-struts-2-actions-spring-junit /

Комментарии:

1. спасибо за ответ. с тех пор я перешел с Struts2 на Spring MVC и, следовательно, не могу легко подтвердить это решение в моем старом проекте. поскольку это единственный ответ, полученный на этот вопрос (и, похоже, он должен сработать), я собираюсь пойти дальше и принять его. большое спасибо!

2. У меня была такая же ошибка, я отследил ее до TilesResult NPE, и это устранило мою проблему. Спасибо!

3. У меня такая же проблема, но я не использую Spring и, следовательно, я расширяю StrutsJUnit4TestCase — каким будет решение в моем случае?

Ответ №2:

Он пытается отобразить страницу jsp. Поэтому отключите, добавив ExecuteResult(false) в коде.

Итак, добавьте строку ниже

 proxy.setExecuteResult(false); 
  

перед proxy.execute()