1

In the Testcontainers documentation, there is an example for having the docker image to be parameterized with @ParameterizedTest.

This was a junit4 example.

https://github.com/testcontainers/testcontainers-java/blob/main/core/src/test/java/org/testcontainers/junit/ParameterizedDockerfileContainerTest.java

@RunWith(Parameterized.class)
public class ParameterizedDockerfileContainerTest {

    private final String expectedVersion;

    @Rule
    public GenericContainer container;

    public ParameterizedDockerfileContainerTest(String baseImage, String expectedVersion) {
        container =
            new GenericContainer(
                new ImageFromDockerfile()
                    .withDockerfileFromBuilder(builder -> {
                        builder
                            .from(baseImage)
                            // Could potentially customise the image here, e.g. adding files, running
                            //  commands, etc.
                            .build();
                    })
            )
                .withCommand("top");
        this.expectedVersion = expectedVersion;
    }

    @Parameterized.Parameters(name = "{0}")
    public static Object[][] data() {
        return new Object[][] { //
            { "alpine:3.12", "3.12" },
            { "alpine:3.13", "3.13" },
            { "alpine:3.14", "3.14" },
            { "alpine:3.15", "3.15" },
            { "alpine:3.16", "3.16" },
        };
    }

    @Test
    public void simpleTest() throws Exception {
        final String release = container.execInContainer("cat", "/etc/alpine-release").getStdout();

        assertThat(release).as("/etc/alpine-release starts with " + expectedVersion).startsWith(expectedVersion);
    }
}

I couldn't find a way to do something similar with junit5, basically :

  • having the container only started once for all the @ParameterizedTest methods in the class

Ofc, with a lot of if/else, playing with beforeEach, TestInfo, ... is possible but I feel like something is wrong and I'm sure the following question has probably should be answered with junit5

How to use parameterized tests for testing with multiple database versions

Christophe Willemsen
  • 19,399
  • 2
  • 29
  • 36

2 Answers2

5

So, it seems the equivalent to junit5 is not possible, related to this opened issue https://github.com/junit-team/junit5/issues/878#issuecomment-546459081 as mentioned by Eddù above

With the great help of Michael Simons, I could manage to do something that works

Base class :

@Testcontainers(disabledWithoutDocker = true)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class MultipleNeo4jVersionsTest {

    protected static String HEAP_SIZE = "256M";

    public static Stream<String> neo4jVersions() {
        return Stream.of("4.4.14", "5.2.0");
    }

    protected static String heapSizeSetting(Neo4jVersion version) {
        return version.equals(Neo4jVersion.V4_4)
                ? "NEO4J_dbms_memory_heap_max__size"
                : "NEO4J_server_memory_heap_max__size"
                ;
    }

    protected Neo4jContainer<?> getNeo4j(String version) {
        var imageName = String.format("neo4j:%s-enterprise", version);
        Neo4jVersion neo4jVersion = Neo4jVersion.of(version);
        Neo4jContainer<?> container = new Neo4jContainer<>(imageName)
                .withoutAuthentication()
                .withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes")
                .withEnv(heapSizeSetting(neo4jVersion), HEAP_SIZE)
                .withReuse(true);
        container.start();

        return container;
    }
}

And the actual test class

@ParameterizedTest
    @MethodSource("neo4jVersions")
    void loading_config(String version) throws Exception {
        Neo4jContainer<?> neo4j = getNeo4j(version);
        // do something here

    }

Couple of useful links

Christophe Willemsen
  • 19,399
  • 2
  • 29
  • 36
0

Devopology Test Engine (Junit5 based) supports parameterized class testing. (I'm the author)

https://github.com/devopology/test-engine

Your example...

package test.neo4j;

import org.devopology.test.engine.api.AfterAll;
import org.devopology.test.engine.api.BeforeAll;
import org.devopology.test.engine.api.Parameter;
import org.devopology.test.engine.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.containers.wait.strategy.Wait;

import java.util.ArrayList;
import java.util.Collection;

public class Neo4jTest {

    @Parameter
    public String dockerImageName;

    @Parameter.Supplier
    public static Collection<String> dockerImageNames() {
        Collection<String> dockerImageNames = new ArrayList<>();
        dockerImageNames.add("neo4j:4.4.14-enterprise");
        dockerImageNames.add("neo4j:5.2.0-enterprise");
        return dockerImageNames;
    }

    private Neo4jContainer<?> neo4jContainer;

    @BeforeAll
    public void beforeAll() {
        neo4jContainer = new Neo4jContainer<>(dockerImageName)
                .waitingFor(Wait.forLogMessage(".*Started..*", 1))
                .withEnv("NEO4J_ACCEPT_LICENSE_AGREEMENT", "yes")
                .withEnv(heapSizeSetting(dockerImageName), "256M")
                .withLogConsumer(outputFrame -> System.out.print(outputFrame.getUtf8String()))
                .withoutAuthentication();

        neo4jContainer.start();
    }

    @Test
    public void test1() {
        System.out.println("test1 : dockerImageName = [" + dockerImageName + "]");

        // do something here
    }

    @Test
    public void test2() {
        System.out.println("test2 : dockerImageName = [" + dockerImageName + "]");

        // do something here
    }

    @AfterAll
    public void afterAll() {
        if (neo4jContainer != null) {
            try {
                neo4jContainer.close();
            } catch (Throwable t) {
                // DO NOTHING
            }

            neo4jContainer = null;
        }
    }

    protected static String heapSizeSetting(String dockerImageName) {
        return dockerImageName.contains("4.4")
                ? "NEO4J_dbms_memory_heap_max__size" : "NEO4J_server_memory_heap_max__size";
    }
}
Doug Hoard
  • 11
  • 4