Advertisement

StrutsTestCase with JUnit in Eclipse: ( Version: Struts1.*)

HTML clipboard JUnit is a simple open source Java testing framework used to write and run repeatable automated tests. It is an instance of the xUnit architecture for unit testing framework. 

Eclipse comes with JUnit built into the Workbench. Eclipse allows you to quickly create test case classes and test suite classes to write your test code in. With Eclipse, Test Driven Development (TDD), becomes very easy to organize and implement.
The class that you will want to test is created first so that Eclipse will be able to find that class under test when you build the test case class. The test cases are built with the needed imports and extensions for JUnit to run. Once the test case class is built the actual test cases are then coded in by the programmer.
The creation of test suites in Eclipse is even easier. When you create a test suite, Eclipse will name it for you and will specify all of the test cases in the scope of the project that it can find. 
JUnit features include

Reminder of JUnit Naming Conventions



Assertion statements

This is a list of the different types of assertion statements that are used to test your code. Any Java data type or object can be used in the statement. These assertions are taken from the JUnit API.

· assertEquals(expected, actual)
· assertEquals(message, expected, actual)
· assertEquals(expected, actual, delta) - used on doubles or floats, where delta is the difference in precision
· assertEquals(message, expected, actual, delta) - used on doubles or floats, where delta is the difference in precision
· assertFalse(condition)
· assertFalse(message, condition)
· assertNotNull(object)
· assertNotNull(message, object)
· assertNotSame(expected, actual)
· assertNotSame(message, expected, actual)
· assertNull(object)
· assertNull(message, object)
· assertSame(expected, actual)
· assertSame(message, expected, actual)
· assertTrue(condition)
· assertTrue(message, condition)
· fail()
· fail(message)
· failNotEquals(message, expected, actual)
· failNotSame(message, expected, actual) 
· failSame(message)

TestRunner

TestRunner is the Java program that will systematically run each of the testMethods that you wrote in your TestXxxxx class. It will also automatically track and report the successes and failures recorded. The console version is good, but the graphic versions allow you to see a GREEN BAR when all tests pass. If any test fails, you will see a RED BAR instead. This visual information regarding the successes and failures of your implementation is not only useful, it is great fun to see. 

Run TestRunner to see the results of your testMethods

Each of these commands assumes that you are in the parent directory of the application.

Console Window 

java -classpath ".;c:\junit3.8.1\junit.jar" junit.textui.TestRunner junit.sample.AllTests
AWT GUI Frame 
java -classpath ".;c:\junit3.8.1\junit.jar" junit.awtui.TestRunner junit.sample.AllTests
Swing GUI Frame 
java -classpath ".;c:\junit3.8.1\junit.jar" junit.swingui.TestRunner junit.sample.AllTests


Struts

Struts is a framework that promotes the use of the Model-View-Controller architecture for designing large scale applications. The framework includes a set of custom tag libraries and their associated Java classes, along with various utility classes. The most powerful aspect of the Struts framework is its support for creating and processing web-based forms.

Model-View-Controller" is a way to build applications that promotes complete separation between business logic and presentation. It is not specific to web applications, or Java, or J2EE (it predates all of these by many years), but it can be applied to building J2EE web applications.

Diagram for Struts Workflow



StrutsTestCase 

StrutsTestCase for JUnit is an extension of the standard JUnit TestCase class that provides facilities for testing code based on the Struts framework. StrutsTestCase provides both a Mock Object approach and a Cactus approach to actually run the Struts ActionServlet, allowing you to test your Struts code with or without a running servlet engine. Because StrutsTestCase uses the ActionServlet controller to test your code, you can test not only the implementation of your Action objects, but also your mappings, form beans, and forwards declarations. And because StrutsTestCase already provides validation methods, it's quick and easy to write unit test cases.

MockStrutsTestCase and CactusStrutsTestCase
There are two popular approaches to testing server-side classes: mock objects, which test classes by simulating the server container, and in-container testing, which tests classes running in the actual server container. StrutsTestCase for JUnit allows you to use either approach, with very minimal impact on your actual unit test code. In fact, because the StrutsTestCase setup and validation methods are exactly the same for both approaches, choosing one approach over the other simply effects which base class you use!

StrutsTestCase for JUnit provides two base classes, both of which are extensions of the standard JUnit TestCase. MockStrutsTestCase uses a set of HttpServlet mock objects to simulate the container environment without requiring a running servlet engine. CactusStrutsTestCase uses the Cactus testing framework to test Struts classes in the actual server container, allowing for a testing environment more in line with the actual deployment environment.

Note: While the following examples use the MockStrutsTestCase approach, you could choose to use the Cactus approach by simply subclassing from CactusStrutsTestCase without changing another line of code.

Sample on StrutsTestCase with JUnit

Now we can see example on StrutsTestCase with Eclipse. That will help the web developers to test their application in simpler way. In this article I have presented a sample which extends MockStrutsTestCase. 

Suppose we have a sample for Login to an application. The test case should have various test inputs to test Login. The ActionForm will have the inputs as username and password. The test case should pass various values to the parameters username and password to validate the Login.
The following are the steps to develop an application in struts and test it with strutstestcase.

1) Download sturts framework and strutstestcase from www.sourceforge.net .
2) Download Junit jar if it is not available with your eclipse installed. Later versions of Eclipse will have Junit plugin by default.
3) Click File à New à Project à Give project name ( say StrutsTestCase )
4) Right click on your project name in Project Explorer perspective view à New à Source Folder à Give name ( say src ) or else choose from File menu.
5) Right click on project name à New à Folder à Give name ( WEB-INF ).
6) Create web.xml file by Right click on WEB-INF folder à New à File à Give name (web.xml)
7) Create struts-config.xml file by Right click on WEB-INF folder à New à File à Give name (struts-config.xml)
8) Copy necessary struts tld file to WEB-INF directory.



9) Right click on project name à New à Folder à lib. Copy necessary jar files to your lib directory.
10) Right click on project name à New à Folder à Give name ( jsp ).
11) Build classpath by Right click on project name à Build Path à configure Build Path…



12) Add necessary jars in Java Build Path option as following. Struts-1.2.jar, strutstest-2.1.4.jar , servlet-api.jar are necessary for MockStrutsTestCase.



13) Create package by Right click on src à New à Package à Give name (com.apache.struts)
14) Create java class files by Right click on package à New à Class à Give Name ( LoginAction )
15) Create java class files by Right click on package à New à Class à Give Name (LoginForm)
16) Create JunitTestCase by Right click on package à New à JUnitTestCase à Give name (LoginActionTest)
17) TestCase should extend either MockStrutsTestCase (if you are running in command prompt or eclipse) or CactusStrutsTestCase(it will need ServletEngine to run TestCase)

i) Check which method stubs you would like to create. You can create a main method, setUp(), tearDown(), or a constructor(), but all of these are optional. A constructor is only run when the test case class is first instantiated, but the setUp() and tearDown() methods are run before and after, respectively, each test case is run.

18) create jsp files by Right click on jsp à New à File àGive name (Login.jsp)
19) create jsp files by Right click on jsp à New à File àGive name (Success.jsp). 
20) Run your TestCase by Right click on TestCase à Run As à JunitTestCase or Java Application.

As I have specified that JUnit has three way (textui, awtui, swingui) to run our test cases, I have used textui TestRunner for the testcases. 
Note:

1) The package structure for java classes and JunitTestCase should be same. 
2) Test class name should be same as Class name followed by Test.
3) Test methods should be same as specified above.

Sample Code:

LoginAction.java
package com.apache.struts;
import org.apache.struts.action.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**

* @author subbulakshmi_g
* @web http://sites.google.com/site/suseeganesan
* @email subbuseema@gmail.com / subbu_seema@yahoo.co.in 

*/
public class LoginAction extends Action {

private String userName;
private String password; 
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
LoginForm loginForm = (LoginForm) form;
userName = loginForm.getUsername();
password = loginForm.getPassword(); 
ActionErrors errors = new ActionErrors(); 
if ((!userName.equals("struts")) || (!password.equals("apache")))
errors.add("password",new ActionMessage("error.password.mismatch"));
if (!errors.isEmpty()) {
saveErrors(request,errors);
return new ActionForward(mapping.getInput());
}
HttpSession session = request.getSession();
session.setAttribute("authentication", userName);
return mapping.findForward("success");
}
}
LoginForm.java
package com.apache.struts;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

/**

* @author subbulakshmi_g
* @web http://sites.google.com/site/suseeganesan
* @email subbuseema@gmail.com / subbu_seema@yahoo.co.in 

*/
public class LoginForm extends ActionForm {

private String username;
private String password;
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return this.username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
Login.jsp
<%@ taglib uri="/tags/struts-html" prefix="html" %>

<h2>Login Here</h2>
<h2>user="struts" and password="struts"</h2>

<html:form action="/LoginAction" >
username:&nbsp;<html:text property="username"/>
<br/>
password:&nbsp;<html:password property="password"/>
<br/>
<html:errors />
<html:submit/>
</html:form>
Success.jsp
<h2>You have successfully logged in!</h2>
<a href="/test/login/login.jsp">Go back</a>
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

<context-param>
<param-name>username</param-name>
<param-value>struts</param-value>
</context-param>
<!-- Cactus Servlet Redirector configuration -->
<servlet>
<servlet-name>ServletRedirector</servlet-name>
<servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>
</servlet>
<!-- Action Servlet Configuration -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>application</param-name>
<param-value>examples.ApplicationResources</param-value>
</init-param>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>config/tiles</param-name>
<param-value>/WEB-INF/struts-config-tiles.xml</param-value>
</init-param>
<init-param>
<param-name>config/test</param-name>
<param-value>/WEB-INF/struts-config-test.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>3</param-value>
</init-param>
<init-param>
<param-name>validating</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!-- Cactus Servlet Redirector URL mapping -->
<servlet-mapping>
<servlet-name>ServletRedirector</servlet-name>
<url-pattern>/ServletRedirector</url-pattern>
</servlet-mapping>
<!-- Action Servlet Mapping -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>/login/login.jsp</welcome-file>
</welcome-file-list>
<!-- Struts Tag Library Descriptors -->
<taglib>
<taglib-uri>/tags/struts-bean</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-html</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-logic</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/tags/struts-form</taglib-uri>
<taglib-location>/WEB-INF/struts-form.tld</taglib-location>
</taglib>
</web-app>
struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<struts-config>
<!-- ========== Form Bean Definitions =================================== -->
<form-beans>
<form-bean name="loginForm" type="com.apache.struts.LoginForm"/>

</form-beans>
<!-- ========== Global Forward Definitions ============================== -->
<global-forwards> 

</global-forwards>
<!-- ========== Action Mapping Definitions ============================== -->
<action-mappings>
<!-- Process a user logon -->
<action path="/LoginAction" type="com.apache.struts.LoginAction" name="loginForm" input="/jsp/Login.jsp" scope="request">
<forward name="success" path="/jsp/Success.jsp"/>
<forward name="failure" path="/jsp/Login.jsp"/>
</action>
</action-mappings>

<!-- specify controller so that tests work with struts 1.3 -->
<controller processorClass="org.apache.struts.action.RequestProcessor" /> 

</struts-config>
LoginActionTest.java
package com.apache.struts;

import servletunit.struts.MockStrutsTestCase;

/**

* @author subbulakshmi_g
* @web http://sites.google.com/site/suseeganesan
* @email subbuseema@gmail.com / subbu_seema@yahoo.co.in 

*/
public class LoginActionTest extends MockStrutsTestCase {

public LoginActionTest(String testName) {
super(testName);
}

public void setUp() throws Exception {
super.setUp();
setInitParameter("validating","false");
}

public void testSuccessfulLogin() {

addRequestParameter("username","struts");
addRequestParameter("password","apache");

setRequestPathInfo("/LoginAction");
actionPerform();

verifyForward("success");
verifyForwardPath("/jsp/Success.jsp");
assertEquals("struts",getSession().getAttribute("authentication"));
verifyNoActionErrors();
}

public void testFailedLogin() {

addRequestParameter("username","struts");
addRequestParameter("password","name");

setRequestPathInfo("/LoginAction");
actionPerform();

verifyForward("failure");
verifyForwardPath("/jsp/Login.jsp");
verifyInputForward();
verifyActionErrors(new String[] {"error.password.mismatch"});
assertNull(getSession().getAttribute("authentication"));

addRequestParameter("username","apache");
addRequestParameter("password","struts");

setRequestPathInfo("/LoginAction");
actionPerform();

verifyForward("failure");
verifyForwardPath("/jsp/Login.jsp");
verifyInputForward();
assertNull(getSession().getAttribute("authentication"));

addRequestParameter("username","");
addRequestParameter("password","");

setRequestPathInfo("/LoginAction");
actionPerform();

verifyForward("failure");
verifyForwardPath("/jsp/Login.jsp");
verifyInputForward();

}

public static void main(String[] args) {
junit.textui.TestRunner.run(LoginActionTest.class);
}

}


This is a simple sample to explain about strutstestcase/MockStrutsTestCase. We can see some other samples for how the MockStrutsTestCase will work for ActionForm when submitting files for uploading or to get object for getRealPath(“/”) as well as sample for CactusStrutsTestCase in my next tutorial. If you need more details visit the following sites.

References:

http://struts.apache.org/1.x/userGuide/introduction.html
http://j2ee.masslight.com/Chapter4.html
http://strutstestcase.sourceforge.net/
http://open.ncsu.edu/se/tutorials/junit/
http://www.laliluna.de/assets/tutorials/junit-testing-en.pdf


About Author

You can reach the author from the following emails.
subbu_seema@yahoo.co.in,subbuseema@gmail.com








Added on July 3, 2010 Comment

Comments

Post a comment