Sunday, March 30, 2008

JUNIT with Struts 2

lets c how to write Junit test cases for an application written in Struts2. The biggest problem i encountered is that theres hardlt any documentation abt this... by struggling over the net i discovered a way to circumvent the problem. The code goes as follows.

basically here we are see if the Entries made in Struts.xml (i.e. that we give using <> tag etc... ) is working fine or not.

Create a base Test case:
package com.company

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.mock.MockServletConfig;
import org.apache.struts.mock.MockServletContext;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.util.StrutsTestCaseHelper;

import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;

import junit.framework.TestCase;

public class BaseS2TestCase extends TestCase {
private Dispatcher dispatcher;
protected ActionProxy proxy;
protected static MockServletContext servletContext;
protected static MockServletConfig servletConfig;
protected HttpServletRequest request;
protected HashMap requestParameters = new HashMap();
protected HttpServletResponse response;

public BaseS2TestCase(String name) {
super(name);
}

/**
* Creates action class based on namespace and name
*
* @param clazz
* Class for which to create Action
* @param namespace
* Namespace of action
* @param name
* Action name
* @return Action class
* @throws Exception
* Catch-all exception
*/
@SuppressWarnings("unchecked")
protected T createAction(Class clazz, String namespace, String name)
throws Exception {
dispatcher = StrutsTestCaseHelper.initDispatcher(null);
// dispatcher = Dispatcher.getInstance();
proxy = dispatcher.getContainer().getInstance(ActionProxyFactory.class)
.createActionProxy(namespace, name, null, true, false);
proxy.getInvocation().getInvocationContext().setParameters(
requestParameters);

// do not execute the result after executing the action
proxy.setExecuteResult(true);

// set the actions context to the one which the proxy is using
ServletActionContext.setContext(proxy.getInvocation()
.getInvocationContext());
ServletActionContext.setRequest(request);
ServletActionContext.setResponse(response);
ServletActionContext.setServletContext(servletContext);
return (T) proxy.getAction();
}

/**
* The method(X) mentioned in < name="..." method="X" class="C"> tag is
* invoked on the class(C) and the string-result is returned.
*
* @return: action result, eg: SUCCESS, FAILURE etc as returned by the
* action method
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
protected String execActionMethod() throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException {
Object action = proxy.getAction();
Method method = action.getClass().getMethod(proxy.getMethod(), null);
Object result = method.invoke(action, null);
return (String) result;
}
}


and now extend this class and get the juint running :)

public class newTest extends EdsBaseTestCase {

public EdsWizardTest(String name) {
super(name);
}

protected void setUp() throws Exception {
super.setUp();
}

protected void tearDown() throws Exception {
super.tearDown();
}

public void testEventAttributes() throws Exception {
EdsWizard action = createAction(EdsWizard.class, "/eds",
"eventAttributes");
// String method = proxy.getMethod();
String exec = execActionMethod(); // action.eventAttributes();
assertEquals(exec, "success");
}
}

Thats it. You are done. Please let me know if u see any issues with this approach.

cheers,
coffee

2 comments:

  1. When I add the base class I get an error about T being undefined - how to fix this? thx and thx for posting this article

    ReplyDelete
  2. Thanks , Its working ...

    ReplyDelete