Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


StrutsTestCase: Drilled-down Testing for Struts-based Java Apps : Page 4

This article demonstrates both mock testing and in-container testing of Web-based applications built with the Struts Model-View-Controller framework. StrutsTestCase, a small testing library that builds on top of the JUnit testing framework, allows you to perform both testing methodologies on Struts applications.


WEBINAR: On-demand Event

Unleash Your DevOps Strategy by Synchronizing Application and Database Changes REGISTER >

Time to Run the Tests
You are now ready to run the tests. First, start up Tomcat. Then, deploy the tests by typing ant deploy. Now type ant run-container-tests. You should see something similar to the following:

Buildfile: build.xml init: create-unpacked-layout-dirs: compile-classes: create-test-dirs: compile-tests: post-compile-tests-init: test-container-delete: [java] . [java] Time: 0.985 [java] OK (1 test) run-container-tests: BUILD SUCCESSFUL Total time: 3 seconds

You can invoke an undeploy target by typing ant undeploy. The undeploy target removes the phonelist-strutstestcase application and the server-side Cactus tests (which are embedded in the phonelist-strutstestcase application) from the Tomcat deployment directory. You should then shut down Tomcat and restart it. Type ant deploy again to deploy the application again. This sequence of steps updates Tomcat with changes to either your Web application or the Cactus tests you write.

Let's examine what the TestDeleteAction class does. Note that the class inherits from CactusStrutsTestCase, which allows it to perform in-container testing. The first important piece of code to examine is the testDelete method, because the rest of the code in the TestDeleteAction class (composed of the import statements and the other methods) is a boilerplate that you have already seen. Here is the testDelete method stripped of comments:

public void testDelete() { setRequestPathInfo("/showList"); actionPerform(); List contactBeanList = null; int oldSize = -1; contactBeanList = ContactDatabase.getList(); oldSize = contactBeanList.size(); setRequestPathInfo("/delete"); Integer[] deletedIdArray = new Integer[] {new Integer(0), new Integer(2),
new Integer(4)}; String[] deletedIdStringArray = new String[deletedIdArray.length]; for(int i = 0; i < deletedIdArray.length; i++) { deletedIdStringArray[i] = deletedIdArray[i].toString(); } addRequestParameter("id", deletedIdStringArray); actionPerform(); verifyForward("success"); contactBeanList = ContactDatabase.getList(); int newSize = contactBeanList.size(); assertEquals("oldSize - newSize", oldSize - newSize, deletedIdArray.length); boolean deletedElementStillPresent = false; for(int i = 0; i < contactBeanList.size(); i++) { ContactBean contactBean = (ContactBean)contactBeanList.get(i); for(int j = 0; j < deletedIdArray.length; j++) { Integer id = deletedIdArray[j]; if (contactBean.getId().equals(id)) { deletedElementStillPresent = true; break; } } if (deletedElementStillPresent) { break; } } assertFalse("deletedElementStillPresent", deletedElementStillPresent); try { InitialContext iniCtx = new InitialContext(); String stringFromJndi = (String)iniCtx.lookup("java:comp/env/aJndiBinding"); assertEquals("aJndiBinding", stringFromJndi, "Jonas Salk"); } catch (NamingException e) { throw new RuntimeException(e); } }

The code above has several interesting aspects. First, I call ContactDatabase.getList() on the seventh line. Remember that ContactDatabase is a server-side construct, so normally you would not be able to access it directly with black box testing. In addition to retrieving data from the container's environment, I can also modify data in the container's environment and call classes directly to exercise their full functionality and isolate bugs quickly.

Note the JNDI access also. In this case, the retrieval of the JNDI binding is a contrived example because it has nothing to do with deleting contacts. However, it illustrates how an in-container test has access to all of the data in the container environment, including JNDI bindings. Accessing the JNDI binding for a String environment variable is marginally useful. Accessing a JNDI binding for a database connection, a database pool, or other hardware or software resources is essential because your application may require that access. It is difficult, if not impossible, to test an application when all of its required resources are not available.

Keep Mindful of Your Tests
Your foray into unit testing with StrutsTestCase should arm you with the knowledge necessary to begin outfitting your Web applications, whether Struts-based or not, with tests that improve robustness and accelerate the software development process. As you begin to use the testing frameworks described in my previous HttpUnit articles and this article, keep in mind that tests are only as good as the thought you put into them. You should exercise as much care with tests as with the application code.

Wellie Chao has been active in the business of technology for many years, has been involved with software and hardware since 1984, and has been writing Web-based software in a variety of languages and on different platforms since 1994. .
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date