More action with Struts 2
In a recent review of Struts 2 in Action, JW Blogger Oleg Mikheev notes that Struts 2 is "just a collection of extensions built upon WebWork, which is ultimately the right thing to learn before starting a Struts 2 project." While Struts 2 has some architectural flaws, Oleg calls WebWork well-designed, well-tested, and reliable. What are your experiences using Struts 2 and WebWork?

Also see "Hello World the WebWork way," a JavaWorld excerpt from WebWork in Action, by Patrick Lightbody and Jason Carreira.

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Test infect your Enterprise JavaBeans

Learn how to test your J2EE components live and in the wild

Page 3 of 6

In addition to helping clarify the requirements, your test cases prevent you from overdesigning or complicating your implementation. After all, when the tests run, you simply stop coding. You also gain the freedom to change your classes more confidently. Instead of wishing you could change a particular piece of code and being unsure what effect it would have on the system, you can now make your changes without worry. Your tests will tell you what the impact of your changes is.

Maintenance also benefits from unit tests. It is often easier to figure out a component's expected use by reading its tests than by reading the object itself. As maintenance developers make changes, they use the unit tests, which give instant feedback. Regression testing doesn't have to take place immediately before release; you can test continually -- every 10 or 15 minutes. You have captured the requirements for your code in the one place guaranteed to live as long as the code -- the code itself.

The JUnit framework, written by Erich Gamma and Kent Beck, enables comprehensive unit testing by making it easy -- even fun -- to write test code. With JUnit, each test case extends the TestCase class. Any public, no-argument method in which the name starts with "test" is executed one at a time. The test methods call the component under test and make one or more assertions about the behavior of that component. JUnit reports the precise location of each failed assertion.

As an example, let's think about a simple telephone number object. What behavior should it have? At a minimum, it will have accessors for the components of a U.S. number: area code, exchange, number, and extension. We should also have a formatter that gives a nice string representation. Remember, we write the test first.

The following idiom starts a test case that can run by itself or be incorporated into a larger suite of tests:

import junit.framework.*;
public class TelephoneNumberTests extends TestCase {
   public static void main(String[] args) {
      junit.textui.TestRunner.run(suite());
   }
   public static TestSuite suite() {
      return new TestSuite(TelephoneNumberTests.class);
   }
}


This test will execute. Since there are no test methods, it reports an error. What do we need to add for test methods? The rule of thumb is: If it can possibly fail, write a test for it. There are some exceptions to this rule, however. For example, since simple accessor methods rarely fail, they rarely are tested. Of course, if your accessor does more than just set an instance variable, you should write a test for it. Choosing precisely what to test takes some practice.

Here is a test method for the string formatting:

   public void testSimpleStringFormatting() throws Exception {
      // Build a complete phone number
      TelephoneNumber number = new TelephoneNumber("612", "630", "1063",
"1623");
      assertEquals("Bad string", "(612) 630-1063 x1623",
number.formatNumber());
   }


The assertEquals() method takes a message string, the expected value, and the actual value. Internally, if expected.equals(actual) returns false, the assertion fails.

Resources