a little madness

A man needs a little madness, or else he never dares cut the rope and be free -Nikos Kazantzakis

Zutubi

Ready to Test: Maven + TestNG + Hamcrest + Mockito

I’m no Maven fanboy, but for a new, small Java project the ultra-fast setup time is compelling. So, for my latest little application, I decided to give it a go. Sadly, the default Maven archetype lumped my project with JUnit 3.8.1. Boo. And although the TestNG website mentions an alternative archetype, it appears to have disappeared off the face of the internet.

Luckily, dragging my project into the present wasn’t difficult. Along the way I also added my essential testing libraries: Hamcrest for matchers and Mockito for mocking (well, stubbing, but that’s another story). For posterity’s sake, and for others that share my testing tastes, here’s how it’s done.

Requirements

I’m assuming that you have Maven 2 installed already. If not, it’s trivial to:

  1. Download the latest (2.1.0 at time of writing); and
  2. Install it according to the instructions provided.

You can check if you have Maven ready to go by running:

$ mvn –version
Apache Maven 2.1.0 (r755702; 2009-03-18 19:10:27+0000)
Java version: 1.6.0_12
Java home: /usr/local/java/jdk1.6.0_12/jre
Default locale: en_AU, platform encoding: UTF-8
OS name: “linux” version: “2.6.28-11-generic” arch: “amd64″ Family: “unix”

Bootstrap

With the lack of an available alternative, I found it easiest to start with the default archetype. To create a new project, run something like:

$ mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app

Remember that if you’ve just installed Maven it will take this opportunity to download the internet. Be patient. If you’re new to Maven, you might also want to check out the 5 minute guide which walks through this in more detail.

Check that your bare application has been created:

$ cd my-app
$ find . -type f
./src/main/java/com/mycompany/app/App.java
./src/test/java/com/mycompany/app/AppTest.java
./pom.xml
$ mvn package

$ java -cp target/my-app-1.0-SNAPSHOT.jar com.mycompany.app.App
Hello World!

Add the Dependencies

Next you need to update the project POM to add the testing libraries as dependencies to your build. This involves three changes:

  1. Removing the default dependency on JUnit.
  2. Adding new dependencies for TestNG, Hamcrest and Mockito to the “test” scope.
  3. Configuring the compiler to accept Java 5 source.

The last step is necessary as the Maven default setting assumes Java 1.3 source, which apart from being ancient doesn’t support goodies such as annotations that are required for the new testing libraries. Your updated pom.xml file should look something like:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>my-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>5.8</version>
      <scope>test</scope>
      <classifier>jdk15</classifier>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.8.0-rc2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.hamcrest</groupId>
      <artifactId>hamcrest-all</artifactId>
      <version>1.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>  
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

I’ve used the latest available versions of each of the libraries in this example — tweak them to suit your current reality.

Update the Sample Test

Now you’re ready to try updating the sample test case to use the trinity of TestNG, Hamcrest and Mockito. The easiest way to do this is to get Maven to generate a project for your IDE, e.g.

$ mvn eclipse:eclipse

or:

$ mvn idea:idea

Fire up your chosen IDE, open the AppTest class, and edit it to exercise all of the dependencies:

package com.mycompany.app;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.testng.annotations.Test;

import java.util.Random;

public class AppTest
{
    @Test
    public void testApp()
    {
        Random mockRandom = mock(Random.class);
        when(mockRandom.nextInt()).thenReturn(42);
        assertThat(mockRandom.nextInt(), equalTo(42));
    }
}

What are you waiting for? Try it out:

$ mvn test

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————
[INFO] Total time: 18 seconds
[INFO] Finished at: Wed Jun 24 16:11:48 BST 2009
[INFO] Final Memory: 20M/100M
[INFO] ————————————————————————

If you got this far, then everything you need is in place. Now you just have to … implement your project!

Extra Credit

If you poke about a bit, you will also find that the maven surefire plugin, which manages the tests, generates some reports by default. Along with HTML output, it also produces a JUnit-like XML report at:

target/surefire-reports/TEST-TestSuite.xml

This report is ideal for integration with a continuous integration server (in my case Pulse, naturally, but many will support it).

Happy testing!

Liked this post? Share it!

2 Responses to “Ready to Test: Maven + TestNG + Hamcrest + Mockito”

  1. June 27th, 2009 at 9:04 am

    Geoffrey Wiseman says:

    Why not share this as a new archetype? “I’d be happy to use ‘Ready to Test’ as an archetype out of central. :)

    “mvn archetype:generate archetypeId=ready-to-test”

  2. June 30th, 2009 at 8:55 pm

    Jason says:

    Hi Geoffrey,

    Indeed, the “proper” way to share this would be a new archetype. I’ve not published one before, but I can look into it.

Leave a Reply