Conteneurs de test Docker dans les tests Java

Conteneurs de test Docker dans les tests Java

1. introduction

In this tutorial, we’ll be looking at Java TestContainers library. Cela nous permet d'utiliser des conteneurs Docker dans nos tests. En conséquence, nous pouvons écrire des tests d'intégration autonomes qui dépendent de ressources externes.

Nous pouvons utiliser toutes les ressources dans nos tests qui ont une image de menu fixe. Par exemple, il existe des images pour les bases de données, les navigateurs Web, les serveurs Web et les files d'attente de messages. Par conséquent, nous pouvons les exécuter en tant que conteneurs dans nos tests.

2. Exigences

La bibliothèqueTestContainers peut être utilisée avec Java 8 et supérieur. De plus, il est compatible avec l'API JUnit Rules.

Tout d'abord, définissons la dépendance maven pour la fonctionnalité principale:


    org.testcontainers
    testcontainers
    1.11.4

Il existe également des modules pour les conteneurs spécialisés. Dans ce didacticiel, nous utiliseronsPostgreSQL andSelenium. 

Ajoutons les dépendances pertinentes:


    org.testcontainers
    postgresql 
    1.11.4


    org.testcontainers
    selenium 
    1.11.4

Nous pouvons trouver les dernières versions surMaven Central.

Also, we need Docker to run containers. Reportez-vous àDocker documentation pour les instructions d'installation.

Assurez-vous que vous êtes en mesure d'exécuter des conteneurs Docker dans votre environnement de test.

3. Usage

Configurons une règle de conteneur générique:

@ClassRule
public static GenericContainer simpleWebServer
 = new GenericContainer("alpine:3.2")
   .withExposedPorts(80)
   .withCommand("/bin/sh", "-c", "while true; do echo "
     + "\"HTTP/1.1 200 OK\n\nHello World!\" | nc -l -p 80; done");

Nous construisons une règle de testGenericContainer en spécifiant un nom d'image docker. Ensuite, nous le configurons avec des méthodes de construction:

  • Nous utilisonswithExposedPorts pour exposer un port depuis le conteneur

  • withCommand définit une commande de conteneur. Il sera exécuté au démarrage du conteneur.

La règle est annotée avec@ClassRule. En conséquence, elle démarrera le conteneur Docker avant que tout test de cette classe ne s'exécute. Le conteneur sera détruit une fois toutes les méthodes exécutées.

Si vous appliquez l'annotation@Rule, la règleGenericContainer lancera un nouveau conteneur pour chaque méthode de test. Et cela arrêtera le conteneur lorsque cette méthode de test se terminera.

We can use IP address and port to communicate with the process running in the container:

@Test
public void givenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse()
  throws Exception {
    String address = "http://"
      + simpleWebServer.getContainerIpAddress()
      + ":" + simpleWebServer.getMappedPort(80);
    String response = simpleGetRequest(address);

    assertEquals(response, "Hello World!");
}

4. Modes d'utilisation

Il existe plusieursusage modesdes conteneurs de test. Nous avons vu un exemple d'exécution d'unGenericContainer.

La bibliothèqueTestContainers a également des définitions de règles avec des fonctionnalités spécialisées. Ils sont destinés aux conteneurs de bases de données communes telles que MySQL, PostgreSQL; et d'autres comme les clients Web.

Bien que nous puissions les exécuter en tant que conteneurs génériques, les spécialisations fournissent des méthodes de commodité étendues.

4.1. Bases de données

Supposons que nous ayons besoin d'un serveur de base de données pour les tests d'intégration de la couche d'accès aux données. Nous pouvons exécuter des bases de données dans des conteneurs à l'aide de la bibliothèque TestContainers.

Par exemple, nous lançons un conteneur PostgreSQL avec la règlePostgreSQLContainer. Ensuite, nous pouvons utiliser des méthodes d'assistance. These are getJdbcUrl, getUsername, getPassword for database connection:

@Rule
public PostgreSQLContainer postgresContainer = new PostgreSQLContainer();

@Test
public void whenSelectQueryExecuted_thenResulstsReturned()
  throws Exception {
    String jdbcUrl = postgresContainer.getJdbcUrl();
    String username = postgresContainer.getUsername();
    String password = postgresContainer.getPassword();
    Connection conn = DriverManager
      .getConnection(jdbcUrl, username, password);
    ResultSet resultSet =
      conn.createStatement().executeQuery("SELECT 1");
    resultSet.next();
    int result = resultSet.getInt(1);

    assertEquals(1, result);
}

Il est également possible d'exécuter PostgreSQL en tant que conteneur générique. Mais il serait plus difficile de configurer la connexion.

4.2. Pilotes Web

Un autre scénario utile consiste à exécuter des conteneurs avec des navigateurs Web. La règleBrowserWebDriverContainer permet d'exécuter les scontainersChrome andFirefox indocker-selenium . Ensuite, nous les gérons avecRemoteWebDriver. 

Ceci est très utile pour automatiser les tests d'interface utilisateur / d'acceptation pour les applications Web:

@Rule
public BrowserWebDriverContainer chrome = new BrowserWebDriverContainer()
  .withCapabilities(new ChromeOptions());
@Test
public void whenNavigatedToPage_thenHeadingIsInThePage() {
    RemoteWebDriver driver = chrome.getWebDriver();
    driver.get("http://example.com");
    String heading = driver.findElement(By.xpath("/html/body/div/h1"))
      .getText();

    assertEquals("Example Domain", heading);
}

4.3. Docker Compose

Si les tests nécessitent des services plus complexes, nous pouvons les spécifier dans un fichierdocker-compose:

simpleWebServer:
  image: alpine:3.2
  command: ["/bin/sh", "-c", "while true; do echo 'HTTP/1.1 200 OK\n\nHello World!' | nc -l -p 80; done"]

Ensuite, nous utilisons la règleDockerComposeContainer. Cette règle va démarrer et exécuter les services tels que définis dans le fichier de composition.

Nous utilisons les méthodesgetServiceHost etgetServicePost pour créer une adresse de connexion au service:

@ClassRule
public static DockerComposeContainer compose =
  new DockerComposeContainer(
    new File("src/test/resources/test-compose.yml"))
      .withExposedService("simpleWebServer_1", 80);

@Test
public void givenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse()
  throws Exception {

    String address = "http://" + compose.getServiceHost("simpleWebServer_1", 80) + ":" + compose.getServicePort("simpleWebServer_1", 80);
    String response = simpleGetRequest(address);

    assertEquals(response, "Hello World");
}

5. Conclusion

Nous avons vu comment nous pourrions utiliser la bibliothèqueTestContainers. Cela facilite le développement et l'exécution des tests d'intégration.

Nous avons utilisé la règleGenericContainer pour les conteneurs d'images Docker données. Ensuite, nous avons examiné les règlesPostgreSQLContainer, BrowserWebDriverContainer etDockerComposeContainer. Ils offrent plus de fonctionnalités pour des cas d'utilisation spécifiques.

Enfin, des exemples de code peuvent être trouvés iciover on GitHub.