cyberpirate92
cyberpirate92

Reputation: 3166

JUnit: How to create a test class with dependency injection via the constructor

How can I create a test class where I can inject the class to be used for testing?

For example, let's say I have a interface ISort and some concrete classes InsertionSort, MergeSort, etc which implement ISort. Since the test cases for all ISort are the same, How can I write a common test class and inject the concrete class to be tested?

This is what I have tried so far

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

public class SortTest {

    private ISort sortingAlgorithm;

    public SortTest(ISort sortingAlgorithm) {
        this.sortingAlgorithm = sortingAlgorithm;
    }

    @Test
    public void test1() {
        int[] data = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int[] expected = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        assertArrayEquals(expected, sortingAlgorithm.sort(data));
    }

    @Test
    public void test2() {
        int[] data = new int[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
        int[] expected = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        assertArrayEquals(expected, sortingAlgorithm.sort(data));
    }

    // .. more tests
}

How to run tests from SortTest using InsertionSortTest class ?

class InsertionSortTest {
    // ??
}

Upvotes: 2

Views: 164

Answers (3)

sotix
sotix

Reputation: 822

Could be done using @Parameterized. You will probably more documentation, just a head start, also using a factory:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class MyTest {

    private static interface SortFactory {
        ISort get();
    }

    private String someOtherParam; // example for more data

    private SortFactory sortFactory;

    public MyTest(SortFactory factory, String someOtherParam) {
        this.sortFactory = factory;

        this.someOtherParam = someOtherParam;
    }

    @Parameterized.Parameters(name = "{1}") // string to show in output to identify tests, here the second parameter
    public static Collection<Object[]> getTestdata() {
        List<Object[]> parameters = new ArrayList<Object[]>();
        parameters.add(new Object[]{ new SortFactory() {
            @Override
            public ISort get() {
                return new MergeSort();
            }
        }, "merge" });
        parameters.add(new Object[]{ new SortFactory() {
            @Override
            public ISort get() {
                return new InsertionSort();
            }
        }, "insertion" });
        return parameters;
    }

    @Test
    public void testSort() {
        int[] given = new int[]{ 2, 1 };

        int[] expected = new int[]{ 1, 2 };

        int[] actual = sortFactory.get().sort(given);

        assertArrayEquals(expected, actual);
    }

}

Upvotes: 0

Morvader
Morvader

Reputation: 2313

Maybe something like this would do the trick.

private static Stream<ISort> sortingType() {
    return Stream.of(new InsertionSort(), new MergeSort());
}

@ParameterizedTest
@MethodSource("sortingType")
public void test1(ISort sortingAlgorithm) {
        int[] data = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        int[] expected = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        assertArrayEquals(expected, sortingAlgorithm.sort(data));
}

Upvotes: 3

Tuan Hoang
Tuan Hoang

Reputation: 686

Have you tried Factory Pattern? Let's create a SortFactory

public class SortFactory {

public ISort getSortingMethod(String method) {
    if(method == null) {
        return null;
    }
    if(method.equalsIgnoreCase("InsertionSort")) {
        return new InsertionSort();
    }

    if(method.equalsIgnoreCase("MergeSort")) {
        return new MergeSort();
    }

    return null;
}
}

and then in your test class, you can use like this

public class SortTest {

private ISort sortingAlgorithm;
private SortFactory sortFactory = new SortFactory();    


@Test
public void test1() {
    int[] data = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int[] expected = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    sortingAlgorithm = sortFactory.getSortingMethod("MergeSort");
    assertArrayEquals(expected, sortingAlgorithm.sort(data));
}

@Test
public void test2() {
    int[] data = new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
    int[] expected = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    sortingAlgorithm = sortFactory.getSortingMethod("InsertionSort");
    assertArrayEquals(expected, sortingAlgorithm.sort(data));
}
}

Upvotes: 1

Related Questions