Programming for fun and profit

Programming tutorials, problems, solutions. Always with code.

JUnit Theories with homemade ParamaterSuppliers

JUnit Theories allow to generate test data using parameter suppliers. In this post we’re going to implement ParameterSupplier that produces Fibonacci numbers and as source of test data.

System Under Test

First let’s create a class that we want to test. It’s a simple class that calculates the sum of all numbers in the given array. To make things simple we use sum() method from Java 8 IntStream:

package com.farenda.junit;

import java.util.Arrays;

public class Summator {

    public int sum(int[] numbers) {

JUnit ParameterSupplier implementation

Now, as you may remember from previous posts we need to implement a ParameterSupplier and create an annotation that will allow user to specify input parameters for the supplier:

package com.farenda.junit;

import org.junit.experimental.theories.ParameterSignature;
import org.junit.experimental.theories.ParameterSupplier;
import org.junit.experimental.theories.ParametersSuppliedBy;
import org.junit.experimental.theories.PotentialAssignment;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;

import static java.util.Collections.singletonList;
import static org.junit.experimental.theories.PotentialAssignment.forValue;

public class FibonacciParameterSupplier extends ParameterSupplier {

    private static final String VALIDATION_ERROR_MESSAGE
            = "\"n\" must be non negative number! Was: %d";

    // The annotation for input parameters:
    public @interface FibonacciNumbers {
         * Number of Fibonacci numbers to return.
        int n();

    // Implementation of Parameter Supplier:
    public List<PotentialAssignment> getValueSources(ParameterSignature sig) {
        FibonacciNumbers ann = sig.getAnnotation(FibonacciNumbers.class);
        return singletonList(forValue("n", calculateFibos(ann.n())));

    private void validatePrecondition(int n) {
        if (n < 0) {
            throw new IllegalArgumentException(
                String.format(VALIDATION_ERROR_MESSAGE, n));

    private int[] calculateFibos(int n) {
        int[] numbers = new int[n];
        int a = 0, b = 1;
        for (int i = 0; i < n; ++i) {
            numbers[i] = b;
            int tmp = b;
            b += a;
            a = tmp;
        return numbers;

Our, homemade parameter supplier just calculates n Fibonacci numbers (see post on Fibonacci numbers in Java). To access input parameters passed through the FibonacciNumbers annotation we use ParameterSignature.getAnnotation() method. Then we validate the input parameter – this is very important step, because invalid behavior in test data generation can result in hours spent debugging the code! (We don’t check here integer overflow only for brevity. ;-)

In the next step, when we know that we’ve got correct input data, so can proceed with calculation of the Fibonacci numbers. To pass generated numbers back we have to create an instance of PotentialAssignment. To do that we use its forValue method as pass name of parameter that we used (n in our case) and the value, which is the array of Fibonacci numbers.

JUnit Theory with ParameterSupplier

Now let’s an actual test. As always with JUnit Theories we have to run it with Theories Runner. Then, to generate the numbers we use @FibonacciNumbers and pass wanted number of data to generate:

package com.farenda.junit;

import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;

import java.util.Arrays;

import static;
import static org.junit.Assert.assertThat;

import com.farenda.junit.FibonacciParameterSupplier.FibonacciNumbers;

public class TheoriesWithHomeMadeParameterSupplierTest {

    private Summator summator = new Summator();

    public void shouldSumNumbers(@FibonacciNumbers(n = 10) int[] numbers) {
        System.out.println("Calculating sum of numbers: " + Arrays.toString(numbers));
        assertThat(summator.sum(numbers), is(143));


When you run the test with negative number (e.g. @FibonacciNumbers(n = -10)) you will receive the following exception thrown from FibonacciParameterSupplier.validatePrecondition(n) method:

java.lang.IllegalArgumentException: "n" must be non negative number! Was: -10

        at com.farenda.junit.FibonacciParameterSupplier.validatePrecondition(
        at com.farenda.junit.FibonacciParameterSupplier.getValueSources(
        at org.junit.experimental.theories.internal.Assignments.potentialsForNextUnassigned(
        at org.junit.experimental.theories.Theories$TheoryAnchor.runWithIncompleteAssignment(
        at org.junit.experimental.theories.Theories$TheoryAnchor.runWithAssignment(
        at org.junit.experimental.theories.Theories$TheoryAnchor.evaluate(
        at org.junit.runners.ParentRunner.runLeaf(
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(
        at org.junit.runners.ParentRunner$
        at org.junit.runners.ParentRunner$1.schedule(
        at org.junit.runners.ParentRunner.runChildren(
        at org.junit.runners.ParentRunner.access$000(
        at org.junit.runners.ParentRunner$2.evaluate(

But when run with a positive number (10 is this case) the test will print the following output as expected:

Calculating sum of numbers: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]


As you can see JUnit Theories with ParameterSuppliers are powerful, flexible and easy to implement! :-)

Share with the World!