如何以Junit 4方式测试Struts2动作?

时间:2011-04-28 09:03:04

标签: junit struts2

有一个用于测试Struts2操作的struts2-junit-plugin,但它似乎要求测试以JUnit 3样式编写,即我不能使用@BeforeClass,@ Test等注释而不能使用BDD样式测试名称如“shouldDoThisAndThat()”。有没有办法结合struts2-junit-plugin和JUnit 4风格的测试?

5 个答案:

答案 0 :(得分:3)

您可能想尝试一下:

http://glindholm.wordpress.com/2008/06/30/unit-testing-struts-2-actions/

我发现它在测试Struts2操作时非常有用。它使用Mockrunner来模拟在servlet容器中运行,因此您可以以任何您喜欢的方式开发测试,包括使用JUnit 4.

答案 1 :(得分:1)

我有同样的问题,这是我如何解决它,它是一个非常简单的基类。

在我的情况下,我使用hibernate,所以如果你不使用它,请省略会话/事务。 这让我们继续使用我发现的所有模拟struts对象。一个简单的测试用例如下。

我仍然需要弄清楚如何注入资源包(i18n字符串)...我将把它添加到基类。

package com.accelarad.unittest;

import org.apache.struts2.StrutsTestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.web.context.WebApplicationContext;

/**
 * Bring Struts JUnit3 into the JUnit4 world
 * 
 * @author kcostilow
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( { 
    "classpath:spring-datasource-unittest.xml", 
    "classpath:spring-test-hibernate.xml", 
    "classpath:spring-context.xml", 
    "classpath:spring-security.xml", 
    "classpath:spring-server.xml"
    }
)
public abstract class AbstractSpringStruts2JUnit4 extends StrutsTestCase implements ApplicationContextAware {

    protected ApplicationContext applicationContext;

    @Autowired
    protected SessionFactory sessionFactory;

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

    @BeforeClass
    public static void initialize() {
        // in my case, I create a mock JNDI here, 
        // including a mailSession using a Wiser mock SMTP server
    }

    @Before
    public void setUp() throws Exception {
        super.setUp(); // use JUnit3 setUp chain. In this case setupBeforeInitDispatcher() will be called
        if (! TransactionSynchronizationManager.hasResource(sessionFactory)) {
            Session session = SessionFactoryUtils.getSession(sessionFactory, true);  // first @Before only
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
        }
    }

    @Override
    protected void setupBeforeInitDispatcher() throws Exception {
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, applicationContext);
        // inject hibernate sessionFactory into Transaction Management, simulating OpenSessionInView
    }

    @AfterClass
    public static void shutdown() {
        // in my case, I shutdown the mock mail server here
    }
}

示例测试用例:

public class MyActionTest extends AbstractSpringStruts2JUnit4 {
    @Test
    public void testOneStrutsAction() throws Exception {
        ActionProxy proxy = super.getActionProxy("/packageName/actionName");
        TestCase.assertEquals("actionName result", "success", proxy.execute());

        MyAction myAction = (MyAction ) proxy.getAction();
        TestCase.assertNotNull(myAction.getSomething());
    }
}

你可以从那里想到它。

答案 2 :(得分:0)

对于那些在这里寻找如何使用Junit测试struts2动作的人来说,这里有一些使用Struts2.3.12& Junit 4

public class TestIoOptimizationAction extends StrutsJUnit4TestCase<IoOptimizationAction> {

    @Test
    public void login() throws Exception {
        request.setParameter("email", "nitin.cool4urchat@gmail.com");
        request.setParameter("password", "22");

        ActionProxy proxy = getActionProxy("login");
        Map<String, Object> sessionMap = new HashMap<String, Object>();
        proxy.getInvocation().getInvocationContext().setSession(sessionMap);
        String result = proxy.execute();
//        String result = executeAction("/login");
        assertEquals("success", result);
        System.out.println(response.getContentAsString());
    }
}

我必须单独嵌入会话地图,因为我正在使用getActionProxy(),而这里是reason

答案 3 :(得分:0)

您的测试类应该扩展StrutsSpringJUnit4TestCase。

答案 4 :(得分:0)

我从kcostilow和coding_idiot的答案中偷了一点,并用StrutsJUnit4TestCase创建了一个抽象类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( { 
    "classpath:spring-datasource-unittest.xml", 
    "classpath:spring-test-hibernate.xml", 
    "classpath:spring-context.xml", 
    "classpath:spring-security.xml", 
    "classpath:spring-server.xml"
    }
)
@Transactional
@TransactionConfiguration(transactionManager = "dataSourceTransactionManager")
public abstract class AbstractSpringStruts2JUnit4<T extends ActionSupport> extends StrutsJUnit4TestCase<T> {

    @Autowired
    @Qualifier("dataSource")
    public void setDataSource(DataSource dataSource) {
        this.dataSource= dataSource;
    }

    @Before
    public void onSetUp() throws Exception {
        super.setUp();
        setupAction();
    }

    protected abstract void setupAction();

}

然后扩展该类以创建测试:

public class SomeActionIntegrationTest extends AbstractSpringStruts2JUnit4<SomeAction> {
    private SomeAction someAction; // SomeAction must extend ActionSupport.

    @Override
    protected void setupAction() {
        ActionProxy proxy = super.getActionProxy("/someAction"); 
        // You might have* to add ".do" to the end of the URI. 
        So, super.getActionProxy("/someAction.do") was the only way I was able to get the proxy.

        someAction = (ActionSupport) proxy.getAction();
        assertNotNull(someAction);  
    }

    @Test
    public void testExecute() throws Exception {
        String result = someAction.execute();
        assertEquals("input", result);
    }
}