Class DockerResource

java.lang.Object
org.junit.rules.ExternalResource
no.mnemonic.commons.junit.docker.DockerResource
All Implemented Interfaces:
org.junit.rules.TestRule
Direct Known Subclasses:
CassandraDockerResource, ElasticSearchDockerResource, MariaDBDockerResource

public class DockerResource extends org.junit.rules.ExternalResource
DockerResource is a JUnit resource which starts up an isolated Docker container in a unit test, for example for integration tests against an external database. It is advised to use DockerResource as a ClassRule because it is expensive to start a Docker container. DockerResource will start up the container only once and will make sure that the container is teared down after all tests (i.e. when the JVM shuts down).

In order to start up a container the following steps are performed:

  1. Initialize a Docker client. If the $DOCKER_HOST environment variable is set it will connect to the Docker installation specified by this variable. Otherwise it will try to connect to localhost on TCP port 2375 (default Docker daemon port).
  2. Initialize and start up a Docker container specified by the name of a Docker image. It is expected that the Docker image is already installed (for example by performing 'docker pull').
  3. Test that the container is reachable. See isContainerReachable() for more information.
  4. Prepare the container with additional data. See prepareContainer() for more information.

After all tests are finished, either successfully, with an exception or by user cancellation, the running container is stopped and removed in order to not leave stale containers behind.

Initialize DockerResource in the following way as a ClassRule:

 @ClassRule
  public static DockerResource docker = DockerResource.builder()
     .setImageName("busybox")
     .setReachabilityTimeout(30)
     .addApplicationPort(8080)
     .build();
 
See DockerResource.Builder for more information on the configuration properties.

This class provides a basic Docker resource but it is most useful to extend it and override isContainerReachable() and prepareContainer() for more specific use cases, for instance when testing a specific database. See CassandraDockerResource as an example.

Proxy settings

The DockerResource will by default use system properties to determine proxy settings when communicating with the docker daemon. To completely disable proxy, you can set the system property "-DDockerResource.disable.proxy=true".

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
    Builder to create a DockerResource.
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    protected
    DockerResource(String imageName, Set<Integer> applicationPorts, String exposedPortsRange, int reachabilityTimeout, boolean skipReachabilityCheck, boolean skipPullDockerImage, Supplier<org.mandas.docker.client.DockerClient> dockerClientResolver, Map<String,String> environmentVariables)
    Constructor to override by subclasses.
  • Method Summary

    Modifier and Type
    Method
    Description
    protected org.mandas.docker.client.messages.ContainerConfig
    additionalContainerConfig(org.mandas.docker.client.messages.ContainerConfig config)
    Subclasses can override this method in order to apply additional configuration to the container itself.
    protected org.mandas.docker.client.messages.HostConfig
    additionalHostConfig(org.mandas.docker.client.messages.HostConfig config)
    Subclasses can override this method in order to apply additional configuration to the host inside the container.
    void
    Teardown DockerResource after executing tests.
    void
    Initialize DockerResource before executing tests.
    Create builder for DockerResource.
    Expose containerID of the started container to subclasses.
    org.mandas.docker.client.DockerClient
    Expose DockerClient used by DockerResource to subclasses.
    Returns the host where the started Docker container is available.
    int
    getExposedHostPort(int applicationPort)
    DockerResource will map the application ports, which are the ports applications listen to inside the container, to random ports on the host machine, which can be used to communicate with the applications.
    protected boolean
    Subclasses can override this method in order to implement a check to determine if a container is reachable.
    protected void
    Subclasses can override this method in order to prepare a container once before tests are executed, for example by initializing a database with a schema or inserting some application data into a database.

    Methods inherited from class org.junit.rules.ExternalResource

    apply

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • DockerResource

      protected DockerResource(String imageName, Set<Integer> applicationPorts, String exposedPortsRange, int reachabilityTimeout, boolean skipReachabilityCheck, boolean skipPullDockerImage, Supplier<org.mandas.docker.client.DockerClient> dockerClientResolver, Map<String,String> environmentVariables)
      Constructor to override by subclasses.
      Parameters:
      imageName - Name of Docker image (required)
      applicationPorts - Application ports available inside the container (at least one is required)
      exposedPortsRange - Range of ports for mapping to the outside of the container (optional)
      reachabilityTimeout - Timeout until testing that container is reachable stops (optional)
      skipReachabilityCheck - If set skip testing that container is reachable (optional)
      skipPullDockerImage - If set skip pulling docker image (optional)
      dockerClientResolver - Function to resolve DockerClient (optional)
      environmentVariables - Container's environment variables (optional)
      Throws:
      IllegalArgumentException - If one of the required parameters is not provided
  • Method Details

    • getExposedHost

      public String getExposedHost()
      Returns the host where the started Docker container is available. It takes the $DOCKER_HOST environment variable into account and falls back to 'localhost' if the variable is not specified.
      Returns:
      Host where the started Docker container is available
    • getExposedHostPort

      public int getExposedHostPort(int applicationPort)
      DockerResource will map the application ports, which are the ports applications listen to inside the container, to random ports on the host machine, which can be used to communicate with the applications. For example, the application port 8080 could be mapped to random port 33333 on the host machine.

      This method returns the exposed host port for a given application port.

      Parameters:
      applicationPort - Application port inside container
      Returns:
      Exposed port on host machine
      Throws:
      IllegalStateException - If mapped host port cannot be determined
    • builder

      public static <T extends DockerResource.Builder<?>> DockerResource.Builder<T> builder()
      Create builder for DockerResource.
      Returns:
      Builder object
    • additionalHostConfig

      protected org.mandas.docker.client.messages.HostConfig additionalHostConfig(org.mandas.docker.client.messages.HostConfig config)
      Subclasses can override this method in order to apply additional configuration to the host inside the container.

      If not overridden the default configuration will be used.

      Parameters:
      config - Default configuration as set up by DockerResource
      Returns:
      Modified host configuration
    • additionalContainerConfig

      protected org.mandas.docker.client.messages.ContainerConfig additionalContainerConfig(org.mandas.docker.client.messages.ContainerConfig config)
      Subclasses can override this method in order to apply additional configuration to the container itself.

      If not overridden the default configuration will be used.

      Parameters:
      config - Default configuration as set up by DockerResource
      Returns:
      Modified container configuration
    • isContainerReachable

      protected boolean isContainerReachable()
      Subclasses can override this method in order to implement a check to determine if a container is reachable. After start up of the container this method will be called until it either returns true or 'reachabilityTimeout' is reached. If the container is not reachable until 'reachabilityTimeout' starting up DockerResource will fail with a TimeoutException.

      If not overridden the method immediately returns true.

      Returns:
      True if container is reachable
    • prepareContainer

      protected void prepareContainer()
      Subclasses can override this method in order to prepare a container once before tests are executed, for example by initializing a database with a schema or inserting some application data into a database. This method is called once after it was determined that the container is reachable by isContainerReachable().

      If not overridden the method does nothing.

    • getDockerClient

      public org.mandas.docker.client.DockerClient getDockerClient()
      Expose DockerClient used by DockerResource to subclasses. Use this client when overriding isContainerReachable() or prepareContainer().
      Returns:
      DockerClient used by DockerResource
    • getContainerID

      public String getContainerID()
      Expose containerID of the started container to subclasses. Use this containerID when overriding isContainerReachable() and prepareContainer() in order to communicate with the started container directly.
      Returns:
      containerID of started container
    • before

      public void before() throws Throwable
      Initialize DockerResource before executing tests. It should not be necessary to override this method.
      Overrides:
      before in class org.junit.rules.ExternalResource
      Throws:
      Throwable - If initialization fails
    • after

      public void after()
      Teardown DockerResource after executing tests. It should not be necessary to override this method.
      Overrides:
      after in class org.junit.rules.ExternalResource