|
|
||
Simon Brown's BlogExtreme Programming ArchivesGlobal setUp() and tearDown() in JUnit testsPosted by simongbrown on April 16, 2004 at 02:43 PM | Permalink | Comments (5)Like many people, I want a way to run some one-time set up and tear down logic and the approach I usually take is to drop some code into a static initializer block in an abstract test case. For example...
public abstract class SomeTestCase extends TestCase {
static {
// perform the "global" set up logic
}
}
Providing that I remember to subclass
public abstract class SomeTestCase extends TestCase {
static {
// perform the "global" set up logic
// and now register the shutdown hook for tear down logic
Runtime.getRuntime().addShutdownHook(new SomeTestCaseShutdownHook());
}
}
This is quite a simple solution and is an alternative to the TestSetup class. As an example, I use it for creating a file structure on disk prior to running some tests and deleting that structure when the tests have run. The only caveat with this solution is that when you run your unit tests through Ant, the Ant ClassLoader executes the static initializer (and resets static variables) more than once. I don't know quite why it does this but if your global set up and tear down logic can safely be run more than once then it's not too much of a problem. Incidentally, this technique runs really well with the IntelliJ JUnit runner. Testing MVC actions, mock objects and code coveragePosted by simongbrown on January 21, 2004 at 08:41 AM | Permalink | Comments (18)Mock objects are the subject of several blogs again this week and they reminded me of a question that several people have asked me. In a web application, how do you unit test an MVC action?
In a previous blog entry, I highlighted the differences between implementations of the Servlet specification when it comes down to security and presented a fairly simple workaround. Subsequently, I now have a class called import ...;
public class LoginAction extends Action {
/**
* Peforms the processing associated with this action.
*
* @param request The HttpServletRequest instance.
* @param response The HttpServletResponse instance.
* @return The name of the next view
*/
public String process(HttpServletRequest request,
HttpServletResponse response)
throws ServletException {
if (request.getUserPrincipal() != null) {
// some J2EE web containers don't allow programmatic access to the
// principal information from resources that don't fall under a
// security constraint - for this reason this information is placed into
// the user's session
AuthenticatedUser user = new AuthenticatedUser();
user.setName(request.getUserPrincipal().getName());
user.setBlogOwner(request.isUserInRole(Constants.BLOG_OWNER_ROLE));
user.setBlogContributor(request.isUserInRole(Constants.BLOG_CONTRIBUTOR_ROLE));
request.getSession().setAttribute(Constants.AUTHENTICATED_USER, user);
}
try {
response.sendRedirect(someUrl);
} catch (IOException ioe) {
throw new ServletException(ioe);
}
return null;
}
So then, how do you test this? Well, the solution that I've adopted is to use mock objects. The reasons? I want to be able to run my unit tests quickly and without the hassle of setting up a web/application server environment and deploying my code into it. A mock object is effectively a stub for some code that is typically implemented elsewhere. In this example, I am choosing to mock out the interfaces provided by the Servlet specification and this entails providing dummy implementations for those interfaces. As with everything, there is some work involved in building these mocks, but thankfully there are several prebuilt mock object implementations available including MockObjects, EasyMock and JMock. Back to the question in hand, with mock objects, testing the action class becomes fairly straightforward. public void testAuthenticatedBlogOwner() {
try {
MockPrincipal principal = new MockPrincipal("simon");
principal.addRole(Constants.BLOG_OWNER_ROLE);
request.setUserPrincipal(principal);
String result = action.process(request, response);
assertNull(result);
assertEquals(someUrl, response.getSendRedirect());
// and also check that an AuthenticatedUser object has been created
AuthenticatedUser user = (AuthenticatedUser)request.getSession().getAttribute(
Constants.AUTHENTICATED_USER);
assertEquals("simon", user.getName());
assertTrue(user.isBlogOwner());
assertFalse(user.isBlogContributor());
} catch (ServletException e) {
fail();
}
}
Like crazybob, I've also taken the approach of generating mock objects using an IDE. With IntelliJ it's straightforward - just create a new class, state that it implements an interface and choose "Implement methods..." from the Code menu. You might ask why I'm not using a prebuilt implementation and the answer is that I just don't need the sort of flexibility that they offer. The code I'm testing only uses a very tiny percentage of the Servlet API and I can easily generate my own simple mocks very quickly using a YAGNI approach. The existing mock object implementations have support for automatic verification, method invocation counts and so on. There's some really clever stuff in there, but I just don't need it ... yet. ;-) Mock objects present an easy way of testing this MVC action and provide a way to test that action outside of the container. MVC actions are often one of the hardest parts of a web application to test, and using mock objects makes testing easier which in turn helps ensure confidence in your code. Saying this though, one thing still eludes me.
Here, an | ||
|
|