11 January 2018

This article has been published on DZone with editor revision so I recommend you to read it there.

## Introduction and motivation

Recently I gave a talk in my local Java User Group about unit testing. Some of the content of the talk was about some popular libraries you can use in your Java project. I’ve reviewed JUnit4, JUnit5 and Spock framework. Many of the attendees were quite surprised with the differences. In this post, I will summarize the most commented: assert, parametrized tests and mocking.

I always like to demonstrate the concepts with examples and live coding so I chose a simple algorithm: Fibonacci number calculator. If you don’t know it, it’s just to generate numbers which are the sum of the two previous ones in the series: `1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377`.

I used the typical (and with very bad performance) implementation:

``````    private static int fibonacci(int n) {
if (n <= 1) return n; else
return fibonacci(n-1) + fibonacci(n-2);
}``````

## JUnit4

I started explaining JUnit4. It makes sense because it’s the most popular library and the base for many others. I started explaining `assertTrue` and then, more advances usages, including `assertEquals`.

``````    @Test
public void improvedFibonacciTestSimple() {
FibonacciWithJUnit4 f = new FibonacciWithJUnit4();
assertEquals(f.fibonacci(4), 3);
}``````

If it’s false, it would give you an error like:

``````java.lang.AssertionError:
Expected :3
Actual   :2``````

Not very spectacular but quite useful.

The next thing was to show how to write a parametrized test, a nice feature very useful for test algorithms. In JUnit4 is quite tricky. You need to create a Collection with the annotation `@Parameters`.

``````    @Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}
});
}``````

Then we create some local variables and a constructor:

``````    private int fInput;
private int fExpected;

public ParametrizedFibonacciJUnit4(int input, int expected) {
fInput = input;
fExpected = expected;
}``````

and finally, we can use the `assertEquals`:

``````    @Test
public void test() {
FibonacciWithJUnit4 f = new FibonacciWithJUnit4();
assertEquals(fExpected, f.fibonacci(fInput));
}``````

It’s quite verbose and if the test fails, you would obtain a message which doesn’t indicate clearly the order or the parameters used (but your IDE probably will help on that):

``````java.lang.AssertionError:
Expected :0
Actual   :1``````

I didn’t explain mocking here because an external library as Mockito is usually required when you want to use mocking with JUnit4. Mockito is great but I didn’t have enough time to explain it.

## JUnit5

Since September 2017, JUnit5 is considered stable and it should be your choice over JUnit4 for several reasons. It has better support for Java 8 and Lambdas, it’s compatible with JUnit4 (you can have both which it’s great to migrate in a progressive way) and it provides new runners and better integrations.

I repeated the same process. First, show an `assertEquals`:

``````    @Test
public void bestFibonacciTestSimple() {
FibonacciWithJUnit5 f = new FibonacciWithJUnit5();
Assertions.assertEquals(f.fibonacci(4), 3);
}``````

There are important advances in other `assert`, for instance the timeout, but for `assertEqual` with integers, it’s practically the same. Also the message is similar if there is an error:

``````org.opentest4j.AssertionFailedError:
Expected :3
Actual   :2``````

Where we can find important changes is in the parametrized test. First, we need to use the `@ParametrizedTest` annotation and we can specify a name using `{` and `}` to indicate important parameters as `index` as `arguments`.

``    @ParameterizedTest(name = "run #{index} with [{arguments}]")``

Now we can define our test. We start defining the entries to test function with the annotation `@CsvSource`. Each item will replace the parameters in the test function, in this case, `input` and `expected`.

``````    @CsvSource({"1, 1", "4, 3"})
public void test2(int input , int expected) {
FibonacciWithJUnit5 f = new FibonacciWithJUnit5();
Assertions.assertEquals(f.fibonacci(input), expected);
}``````

This is lot better than the JUnit4 implementation. Also, if there is a fail in the test, we obtain a better message indicating the difference, the index causing the fail and the used parameters.

Finally, it’s the same for mocking as JUnit4: you normally use an external library so I didn’t explained it.

## Spock framework

The last one was the Spock framework. It’s based in Apache Groovy. If you don’t know Groovy, it’s a language which you can use with the JVM and it interact very well with Java. It allows write less code in a more clear way. It’s very powerful. Some years ago we started to use it for "non critical" development: tests, dependency management, Continuous Integration, load testing and in any place where we need some configuration file avoiding XML, JSON or any format like that. We continue to develop in Java the core of our software and it isn’t a problem because both languages play very well together. If you know Java, you know Groovy…​ so we have the best of both worlds.

Write a test in Spock is quite different, it would be like this:

``````    def "Simple test"() {
setup:

expect:
f.fibonacci(1) == 1
assert f.fibonacci(4) == 3
}``````

Basically, we can use `def` where we don’t care about the type. The name of the function can be defined between quotation marks, which allow us to use better naming for our tests. We have some special words as `setup`, `when`, `expect`, `and`, etc. to define our test in a more descriptive and structured way. And we have a power assert, which is part of the language itself, proving nice messages:

``````Condition not satisfied:

f.fibonacci(4) == 2
| |            |
| 3            false

Expected :2

Actual   :3``````

It provides all the information: the returned value (actual), the expected value, the function, the parameter, etc. `assert` is Groovy is really handy.

Now it’s the turn for the parametrized test. It would be something like this:

``````    def "parametrized test"() {
setup:

expect:
f.fibonacci(index) == fibonacciNumber

where:
index | fibonacciNumber
1     | 1
2     | 1
3     | 2
}``````

After show this I heard some 'oooh' in the audience. The magic of this code is: you don’t need to explain it! There is a table in the `where:` section and the values in `expect:` are automagically replace it in each iteration. If there is a fail, the message is crystal clear:

``````Condition not satisfied:

f.fibonacci(index) == fibonacciNumber
| |         |      |  |
| 2         3      |  4
|                  false

Expected :4

Actual   :2``````

Then I’ve introduced very shortly mocks and stubs. A mock is a object you create in your test to avoid to use a real object. For example, you don’t want to do real web requests or print a page in your tests, so you can use a mock from an interface or another object.

``````    Subscriber subscriber = Mock()

def "mock example"() {
when:
publisher.send("hello")

then:

Basically, you create the `subscriber` interface as Mock and then you can invoke the methods. The `1 *` is another nice feature of Spock, it specify how many messages you should receive. Cool, right?.

In some occasions, you need to define what return the methods of your mocks. For that, you can create a stub.

``````    def "stub example"() {
setup:

when:
publisher.send("message1")

then:
In this case, with the `>>` notation we are defining the method `receive` should return `ok` independently of the parameter (`_` means any value). The test pass without any problem.