Making Maven 2 work with JUnit 4

The current stable version (2.2) of the maven-surefire-plugin does not support JUnit 4. So Maven, out of the box, does not work with JUnit 4. Luckily if we want to use JUnit 4 in our Maven based projects we have two choices. The first is to use JUnit4TestAdapter as illustrated in this post. The second is to use the snapshot version (2.3-SNAPSHOT) of the maven-surefire-plugin that has support for JUnit 4. In a small pet-project I am currently implementing I chose the second option and so far my experience was without any problems.

To use the 2.3-SNAPSHOT you first have to add the Maven snapshot plugin repository into your list of plugin repositories. In your pom.xml add the below XML:

<pluginRepositories>
  <pluginRepository>
    <id>apache.org</id>
    <name>Maven Plugin Snapshots</name>
    <url>http://people.apache.org/repo/m2-snapshot-repository</url>
    <releases>
      <enabled>false</enabled>
    </releases>
    <snapshots>
      <enabled>true</enabled>
    </snapshots>
  </pluginRepository>
</pluginRepositories>

You can also put this configuration into your ~/.m2/settings.xml file to enable this repository for all your projects.

Then go to the maven-surefire-plugin configuration section and change the version from 2.2 to 2.3-SNAPSHOT. For example below I have the maven-surefire-plugin configuration that I use in my pet-project:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.3-SNAPSHOT</version>
  <configuration>
    <includes>
      <include>**/*Test.java</include>
    </includes>
    <forkMode>once</forkMode>
  </configuration>
</plugin>

That’s it, you are done. When you run Maven again the new (2.3-SNAPSHOT) version will be downloaded and you can start using JUnit 4 in you project.

Book Review: Pragmatic Unit Testing

Pragmatic Unit Testing is an easy to read introduction to unit testing. This book covers the basic information you need to know in order to effectively write unit tests.

This book covers in less than 200 pages:

  • What is unit testing and why developers must unit test every piece of code they write.
  • An introduction to unit testing with JUnit.
  • How to effectively write unit tests.
  • Testing on a project.
  • How unit testing affects the design of the code.

The only thing that I didn’t like about this book is the insufficient coverage of the important paradigm of test driver development.

Refactoring from Template Method to Strategy can reduce code duplication in unit tests

Ivan Moore has a great post “Replacing Inheritance with Composition” at his blog, that explains how when you refactor your code from using Template Method to using Strategy can reduce the code duplication in your unit tests and also make your tests simpler.

Both patterns, template method and strategy, try to solve the same problem. Both patterns allow to separate a “high level” algorithm from other algorithms that vary.

The template method design pattern is class based. This pattern has an abstract class that defines the high level algorithm. The abstract class has a set of abstract methods that provide hooks for the extending classes (concrete classes)to implement a specific algorithm.

In template method the high level algorithm is independent of the specific algorithms. On the other hand the specific algorithms (the concrete classes) depend on the abstract class because they extend it and cannot be used and tested without it.

So since the tests of the concrete classes also test the high level algorithm (the code in the abstract class), which is the same for all the concrete classes it is logical for these test to have code duplication. Also since the tests test both the high level algorithm and a specific algorithm they are more complex.

The strategy design pattern is object based. In strategy we have a class (context) that implements the high level algorithm. This class delegates the details (algorithms that vary) to an interface (strategy interface). To implement a specific algorithm you implement the strategy interface (concrete strategies).

In the strategy the high level algorithm is independent of the specific algorithms. Also the specific algorithms do not depend on the high level algorithm, they depend only on the strategy interface. So the they can be used and tested without the context class.

The test of the strategy code are different. Since the context class is not abstract and only depends on an interface (the strategy interface) the context class can be tested in isolation from the concrete strategies using a mock object. This makes the testing code simpler.

The concrete strategies can be tested independently of the context object (because they only depend on the strategy interface) so their tests are simpler and do not have the code duplication that appears in the tests of the concrete classes at the template method implementation.

To make the above more clear read Ivan Moore‘s article that I mentioned at the beginning of this post. You may also want to read this article by Robert C. Martin at java.net about Strategy and Template Method.

TDD and mock objects

If you are new to TDD and to mock objects (like me) you may want to read the paper “Mocks Aren’t Stubs” written by Martin Fowler. In this article Fowler talks about the two testing paradigms, state based and interaction based.

I will use TDD, for the first time, in my next project and I am thinking to choose between easymock and jmock. I like easymock because you set the expectations in a type safe way that allows refactoring with IDE support and auto complete while editing. On the other hand I like jmock because it seems to be more flexible for setting the expectations and because I like the concept of assertThat() (unit testing with constraint objects instead of assertions) introduced by Joe Walnes in his blog.

I don’t know if I will use the interaction based testing since I don’t like the fact that it couples the tests to the implementation. I will surely use the mock toolkit to create stubs for various services, like DAOs and mail abstractions, since it will allow me to test the middle tier without having to configure external systems like databases and mail servers.