spierepf
spierepf

Reputation: 2934

How to get @Testcontainers(disabledWithoutDocker = true) behaviour in junit4/testcontainers

My codebase is ancient and is locked into JUnit4. I would like to integrate testcontainers with the project to incorporate docker containers in the automated tests.

My dev box (which I control) runs docker, however, my CI system (which I do not control) does not.

If I could use JUnit5, I would just add the @Testcontainers(disabledWithoutDocker = true) annotation, and the docker based test would run happily on my dev box, while being disabled on the CI machine.

What is the JUnit4 equivalent to @Testcontainers(disabledWithoutDocker = true)?

Upvotes: 4

Views: 2347

Answers (1)

rieckpil
rieckpil

Reputation: 12041

I'm not sure if there is something out-of-the-box for this in Testcontainers for JUnit 4. You can mirror the JUnit 5 feature with some custom code.

First, you need a way to conditionally execute tests. There is already a good answer for this available. Basically you use JUnit 4 Assumptions for this:

 @Before
 public void beforeMethod() {
     org.junit.Assume.assumeTrue(someCondition());
     // rest of setup.
 }

You will need this for all your Docker related tests.

Next, someCondition() should evaluate whether Docker is available or not. The current Testcontainers (1.14.3) release uses the following code part for @Testcontainers(disabledWithoutDocker = true):

private ConditionEvaluationResult evaluate(Testcontainers testcontainers) {
    if (testcontainers.disabledWithoutDocker()) {
        if (isDockerAvailable()) {
            return ConditionEvaluationResult.enabled("Docker is available");
        }
        return ConditionEvaluationResult.disabled("disabledWithoutDocker is true and Docker is not available");
    }
    return ConditionEvaluationResult.enabled("disabledWithoutDocker is false");
}

boolean isDockerAvailable() {
    try {
        DockerClientFactory.instance().client();
        return true;
    } catch (Throwable ex) {
        return false;
    }
}

So you could extract isDockerAvailable() to e.g. an abstract class that also includes the @Before and handle this for yourself:

public abstract class DockerizedTest {

  @Before
  public void shouldRunTest() {
    org.junit.Assume.assumeTrue(isDockerAvailable());
  }

  boolean isDockerAvailable() {
    try {
      DockerClientFactory.instance().client();
      return true;
    } catch (Throwable ex) {
      return false;
    }
  }

}

and now all your Docker related tests can extend DockerizedTest. Whenever the assumption evaluates to false, the test will be ignored.

If @Before is too late, you can use the same approach with @BeforeClass.

Upvotes: 7

Related Questions