1.23.2011

Testing Toolbelt: SpringJUnit4ClassRunner

The org.springframework.test.context.junit4.SpringJUnit4ClassRunner class is another implementation of the JUnit TestRunner class which is used to enable various features of Spring for every run of the test class and every test within it. To use the features provided by the SpringJUnit4ClassRunner class, you need to mark the class using the RunWith annotation using SpringJUnit4ClassRunner as its parameter.

In addition to the custom test runner, you will want to mark the class with the ContextConfiguration annotation. The ContextConfiguration annotation is used to mark classes which will automatically read a Spring configuration file and use it to create an ApplicationContext. By default, this file located at <package path>/<test class name>-context.xml. Use the locations argument to over-ride.

The ApplicationContext used by the Spring-integrated test will only be loaded once for the whole test class. This behavior can be over-ridden by annotating a test method with the DirtiesContext annotation, which causes the ApplicationContext to be reloaded after the test method completes.

Test Property Injection

Fresh versions of the properties for the test, including the class under test, can be automatically injected for every test, either by name or type. A test class property marked with the Autowired annotation will be automatically set by type from the test's ApplicationContext. However, if there are multiple instances of the property's type, it could be better to set the property by name. The Resource is used to mark test class properties which should be set by name from the test's ApplicationContext.

Transaction Management

With the declaration of a TransactionManager bean, and the use of the Transactional annotation, transaction boundaries are declarative and are automatically managed. Simply fire up the test and forget about whether or not your integration test changed the state of the database you're using to test.

The Transactional annotation is used within transactional Spring tests to mark test classes and methods which should have a transactional nature applied to them. When used to annotate a test class, a transaction context will be created before each test method is executed. After each test method, the transaction will be rolled-back. This will add the overhead of creating and managing a transaction for every test method in that class, so it is usually better to annotate the test methods with @Transactional instead. This will cause a similar effect to annotating the class, but only annotated test methods will be transactional. Usage of this annotation requires a TransactionManager named transactionManager to be defined in the test's ApplicationContext.

Similar in purpose to the Before and After annotations provided by JUnit, methods decorated with either the BeforeTransaction or AfterTransaction annotation will be run before/after any test method which is affected by the Transactional annotation (i.e. all methods in a class decorated with @Transactional, or each annotated test method when marked individually. Methods annotated with the BeforeTransaction or AfterTransaction annotations must be public and return no value.

Integration Test Helper Classes

When using the SpringJUnit4ClassRunner, you're given access to the ApplicationContext instance and a simplified interface for interacting with your integration test database through JdbcTemplate/SimpleJdbcTemplate.

spring-testing-sample.java

Testing Toolbelt: Groovy

Groovy, the apparent golden child of Java, is a mostly dynamic-typed JVM language which seeks to add functionality to the core Java language such that writing and testing code is much easier and requires less boiler-plate code. Some of the features provided by Groovy that I have found useful for testing are:

GroovyBean Properties and Constructors

Groovy attempts to simplify the usage of bean-type object by providing some shortcuts for accesses and assignments. By default, every class accessed through Groovy code is decorated with a default constructor which takes a map (property->value), and a getter and setter for each field defined in the class (for which there is not already a getter/setter). The constructor is a simple way to provide values to properties of the new instance.

properties-sample.groovy

Token Replacement

In Groovy, the String class is enhanced to allow for the use of tokens within a String literal. These tokens are of the form ${<property>} and will use the properties values available at the time of creation. Refer back to the above example to see some at work.

Collection Literals

Easily create a list by using the [] syntax, a range by using the <start>..<end> syntax, and a map by using the [<key>:<value>] syntax.

collection-sample.groovy

Closures

Closures are simply blocks of code surrounded by curly braces, which can be treated as reference types. Closures may declare arguments and may return values. Closures may be stored in variables.

closure-sample.groovy

Iteration (each)

Iteration of arrays, ranges, lists, and maps has been simplified by the addition of the each method.

each-sample.groovy

Coercion (Map and Closure)

Any map or closure may be interpreted as an instance of a specific type simply by using as <type>. This allows you to easily create stand-in objects, provided they have a public default (no-arg) constructor.

coercion-sample.groovy

GDK

Through the default meta-class implementations used by Groovy, many useful methods (many taking advantage of closures) have been added to the standard Java classes. There's too much to list here, but know that many of the above examples use GDK methods.

GroovyTestCase

The GroovyTestCase class contains a large portion of the testing functionality used by basic Groovy. Since the Groovy team have pledged backwards-compatibility with JDK 1.4, they have also stuck with the non-annotation-based version of JUnit(3.8.*) as a basis for their testing helper class. This is not as bad as it sounds, as many of the language features of Groovy make up for the missing capabilities of JUnit 4.4. Every test class defined using groovy must be a sub-class of GroovyTestCase. Each test method must be public, return void, and be named test<something>.

assert*

all of the assert* methods provided by JUnit are also present in the GroovyTestCase class.

shouldFail(<Throwable>)

similar to the Test annotation when used with the expected argument, the shouldFail method takes a Throwable class type and a closure, executes the closure, and fails if an instance of Throwable is not thrown within the closure.

shouldFail-sample.groovy

StubFor and MockFor

The StubFor/MockFor classes can be used within Groovy to create stand-in objects when coercion won't work or when you need to over-ride the behavior of a constructor.

stubfor-sample.groovy

1.22.2011

Spring Note: SqlUpdate

The org.springframework.jdbc.object.SqlUpdate class is another tool that I use a lot. This class encapsulates INSERT, UPDATE, and DELETE queries as beans defined within your application context. In most situations, you will be using the SqlUpdate class as-is with multiple configurations within a DAO's context. Since the class is not abstract, it is quite easy to extend for creating dummy/mock instances for testing.

ITSpringJdbc.java

ITSpringJdbc-context.xml

New Group: Columbus Software Craftsmanship

As you may or may not know, I have two homes: SW Indiana, and Columbus, Ohio. Since I spend 75% or more of my time in SW Indiana and there are few opportunities in this area for networking/learning the craft, I'm always happy to learn about new groups of like-minded people in my other home.

I found this group through a random tweet from Marc Peabody. He mentioned that they would be trying out some Scala Koans and included a link to the group's Google Groups site. Since joining the group earlier today, I've found the details for the Scala Koans night and I've been informed of interest in running a Code Retreat event at the beginning of April in Columbus.

I haven't made it to any meetings yet (they're still a pretty new group), but I've had some friendly conversations in e-mail with members of the group and have met some of the other members through NFJS, COJUG, CRB, etc... Sounds like it should be a pretty good time when I'm able to make it.

Maven note: exec-maven-plugin

I'm currently working on a development package containing a series of .xsd files which will be used to define the external interface for our web service. Due to some other project constraints, it was decided that this package also needed to include the .wsdl files which will further define the web service.

I'm a lazy (the good kind) programmer, so I decided that I did not want to update these files every time the schema changed nor did I want to make anyone else figure it out later. I wrote a quick utility for creating the .wsdl files, based on the current .xsd files. Since we're already expecting to use Spring-WS for message dispatching, I wrote some file generation code around the org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition class and wrote up a Spring configuration which put it all together.

My next task was to figure out a way to get this utility to run within the context of the Maven package phase. Since the code needed to generate the .wsdl files was the only code in this development package, it made sense to hook into the prepare-package phase instead of the generate-sources phase. Now that I knew when the utility should run, I just needed to figure out a way to do it. One Google search later, and I had the exec-maven-plugin. This Maven plugin provides two goals which can be hooked into arbitrary phases in the Maven life cycle:

  • exec -- execute an arbitrary executable from within the Maven runtime
  • java -- execute the main method, with arguments, of a specified class, from within the Maven runtime

So I set up my pom as shown below, and ran mvn package. The end result was a .jar file which contained both the .xsd and the .wsdl files we need. One mvn deploy later and these files were now available to all who needed them.

pom.xml

Testing Toolbelt: Hamcrest Matchers

The Hamcrest Matchers framework contains a series of Matcher classes which help implement comparison and assertion methods in a type-safe, declarative manner. When used in tests, the Matchers framework will produce more legible test code and more helpful failure messages. The Matchers framework is partially included in the JUnit 4.4 package and some portions can be used effectively. But, the full power of the framework can only be unleashed by including the real Hamcrest Matchers jar within your testing environment.

Matchers

The org.hamcrest.Matchers class in the Hamcrest framework provides a series of methods, intended to be used with import static, which supply various pre-defined org.hamcrest.core.Matcher instances.
  • is -- The simplest matcher, most times behaves just as syntactical sugar around other matchers. But, if an instance of Class is passed, it behaves like the Matcher produced by instanceOf. If passed any other value, behaves like the Matcher produced by equalsTo. see org.hamcrest.core.Is
  • equalTo -- Verifies that the test value is equal to the value used to instantiate the Matcher. see org.hamcrest.core.IsEqual
  • instanceOf -- Verifies that the test value is assignable to the Class value used to instantiate the Matcher. see org.hamcrest.core.IsInstanceOf
  • nullValue/nonNullValue -- Verifies that the test value is null-valued/not-null-valued. see org.hamcrest.core.IsNull
  • startsWith/containsString/endsWith -- Verifies that the test value (String\-typed) begins with, contains, or ends with the value used to instatiate the Matcher. see org.hamcrest.core.StringStartsWith, org.hamcrest.core.StringContains, and org.hamcrest.core.StringEndsWith
  • arrayWithSize/emptyArray/hasSize/empty -- Verifies that the test value is an array/collection that either has the given number of elements/is empty. see org.hamcrest.core.IsArrayWithSize, org.hamcrest.core.IsCollectionWithSize, and org.hamcrest.core.IsEmptyCollection
  • lessThan/lessThanOrEqualTo/greaterThanOrEqualTo/greaterThan -- Verifies that the test value is strictly less than/less than/greater than/strictly greater than the provided value. see org.hamcrest.core.OrderingComparison

Examples

Testing Toolbelt: JUnit

The JUnit framework is arguably the de-facto standard for unit testing java code, and is also the basis of many other testing frameworks (unit or otherwise). Using the JUnit framework, one can quickly run a test method, class, or suite and get one of three responses:

  • Success: All of the assertions in the test method passed, no fail calls were encountered, and no unexpected exceptions were thrown.
  • Failure: One of the assertions in the test method failed or a fail call was encountered.
  • Error: An unexpected java.lang.Throwable was thrown within the test method's body.

For the sake of brevity, and since I am mostly using Java 1.6 these days, this discussion will focus on JUnit 4.4 which is based on annotations and static imports instead of specially-named methods and the extension of the junit.framework.TestCase class.

@Test

Every method that should be run as a test should be annotated with the org.junit.Test annotation. The Test annotation must be used on only public void methods and the annotated method can only take parameters when used in conjunction with the Parameterized annotation discussed below. The Test annotation can take two optional arguments:

expected
An optional argument to the Test annotation which declares that the test method is expected to throw a Throwable of the defined type. If the method does not throw a Throwable of an appropriate type, the test will fail. If any other Throwable escapes the method body, the test will be considered in error.
timeout
An optional argument to the Test annotation which declares that the test method is expected to complete within the defined number of milliseconds. If the method does not return in time, the test fails.

@Before/@After/@BeforeClass/@AfterClass

Public methods marked with these annotations will be run before each test (setUp()), after each test(tearDown()), before each test suite, or after each test suite. These annotations are usually used to setup and reset the environment in which the tests are running.

Assert

The org.junit.Assert class is expected to be used through the use of static imports, and contains a large number of static methods which can be used to ensure that the elements of a test are in an expected state. Each of the assert* methods has two forms:

assert*(actual, expected)
performs the assertion and fails with a default failure message.
assert*(message, actual, expected)
performs the assertion and fails with a custom failure message. (sometimes in addition to the default message)

Here are some of the main assertion methods:

assertNull(param)/assertNotNull(param)
Asserts that the parameter is(not) null-valued.
assertTrue(param)/assertFalse(param)
Asserts that the parameter is true|false?
assertEquals(actual, expected)/assertArrayEquals(actual, expected)
Asserts that actual and expected are equal().
fail(message)
Causes the current test to immediately fail. Use this when writing custom assert methods or when creating new empty test methods.
assertThat(actual, Matcher)
The entry point into the Hamcrest Matcher framework, which will be covered by itself in a different post. This method, when used in conjunction with a Matcher instance is more capable, and produces more helpful failure output than the other JUnit assert* methods.

Parameterized

The org.junit.runners.Parameterized class is a non-default JUnit TestRunner implementation which allows for the creation of a series of test class instances, one for each of the parameter sets defined in the parameter generation method. Each of these test class instances will then be executed.

Every class which uses the Parameterized class as a runner must provide a source method for the parameters. The parameter source method is marked using the org.junit.runners.Parameters annotation. The parameter source method must be static and return a Collection of values or arrays. Each element in the returned collection represents a single test class execution and will be passed to the constructor for a new instance of the test class. The constructor must accept the same number of arguments and those arguments must be of a compatible type to those contained in each element of the returned collection.

An example of Parameterized usage:

1.21.2011

Spring Note: RowMapper/MappingSqlQuery

RowMapper

The RowMapper class is an interface which defines only one method which turns a single row from a ResultSet into a domain-useable object. While you can use a generic implementation of this class for producing column name/value Maps, my typical usage has been to create domain objects from the result of a specific set of queries.

MappingSqlQuery

The MappingSqlQuery class is intended to be used for SELECT queries and can use a RowMapper implementation to create a result List of the appropriate type, hiding the intermediate ResultSet from the outside world.

These classes, when taken together, provide excellent tools for creating the read methods for DAO classes which are concise and testable.

ITSpringJdbc.java

ITSpringJdbc-context.xml

Clearing the Backlog

I've had several posts brewing in the background. I'm going to pump out a few posts tonight and finally bid them a fond adieu. So, here they come fast and furious, and maybe not as deep as I originally expected them to be.