diff --git a/core/src/main/java/org/testcontainers/RequireContainerSupportRule.java b/core/src/main/java/org/testcontainers/RequireContainerSupportRule.java new file mode 100644 index 00000000000..b0d74378cdd --- /dev/null +++ b/core/src/main/java/org/testcontainers/RequireContainerSupportRule.java @@ -0,0 +1,38 @@ +package org.testcontainers; + +import org.junit.AssumptionViolatedException; +import org.junit.Rule; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Junit 4 {@code Rule} that will skip the test if the docker client is not available. + * This rule must have a lower {@link Rule#order} specified that any other {@code Rule} that + * uses docker in order to skip tests, otherwise the other rules would fail first causing build failures. + * e.g.

+    {@literal @}Rule(order = -10)
+    public RequireContainerSupportRule rcr = new RequireContainerSupportRule();
+ }
+ * 
+ */ +public class RequireContainerSupportRule implements TestRule { + + @Override + public Statement apply(Statement base, Description description) { + if (DockerClientFactory.instance().isDockerAvailable()) { + return base; + } + return new DockerNotAvailbleStatement(); + } + + private static class DockerNotAvailbleStatement extends Statement { + + @Override + public void evaluate() throws Throwable { + throw new AssumptionViolatedException( + "Docker support is not available and this test requires TestContainers which needs docker" + ); + } + } +} diff --git a/core/src/test/java/org/testcontainers/RequireContainerSupportRuleTest.java b/core/src/test/java/org/testcontainers/RequireContainerSupportRuleTest.java new file mode 100644 index 00000000000..41051441f7c --- /dev/null +++ b/core/src/test/java/org/testcontainers/RequireContainerSupportRuleTest.java @@ -0,0 +1,51 @@ +package org.testcontainers; + +import org.junit.AssumptionViolatedException; +import org.junit.Test; +import org.junit.runners.model.Statement; +import org.mockito.MockedStatic; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +public class RequireContainerSupportRuleTest { + + @Test + public void assumptionViolationisThrownWithoutDockerSpport() { + try (MockedStatic staticallyMockedFactory = mockStatic(DockerClientFactory.class)) { + DockerClientFactory mockedFactory = mock(DockerClientFactory.class); + when(mockedFactory.isDockerAvailable()).thenReturn(false); + staticallyMockedFactory.when(DockerClientFactory::instance).thenReturn(mockedFactory); + + RequireContainerSupportRule rcsr = new RequireContainerSupportRule(); + + assertThatThrownBy(() -> rcsr.apply(new EmptyStatement(), null).evaluate()) + .isInstanceOf(AssumptionViolatedException.class) + .hasMessage("Docker support is not available and this test requires TestContainers which needs docker"); + } + } + + @Test + public void assumptionViolationisNotThrownWithDockerSpport() throws Throwable { + try (MockedStatic staticallyMockedFactory = mockStatic(DockerClientFactory.class)) { + DockerClientFactory mockedFactory = mock(DockerClientFactory.class); + when(mockedFactory.isDockerAvailable()).thenReturn(true); + staticallyMockedFactory.when(DockerClientFactory::instance).thenReturn(mockedFactory); + + RequireContainerSupportRule rcsr = new RequireContainerSupportRule(); + + // any exception thrown will ripple out and fail the test + rcsr.apply(new EmptyStatement(), null).evaluate(); + } + } + + private static class EmptyStatement extends Statement { + + @Override + public void evaluate() throws Throwable { + // no op. + } + } +}