Docker-testcontainers in Java-tests

1. Inleiding

In deze tutorial kijken we naar Java TestContainers bibliotheek. Het stelt ons in staat om Docker-containers te gebruiken binnen onze tests. Als gevolg hiervan kunnen we zelfstandige integratietests schrijven die afhankelijk zijn van externe bronnen.

We kunnen elke bron in onze tests gebruiken die een docker-afbeelding heeft. Er zijn bijvoorbeeld afbeeldingen voor databases, webbrowsers, webservers en berichtenwachtrijen. Daarom kunnen we ze binnen onze tests als containers uitvoeren.

2. Vereisten

TestContainers bibliotheek kan worden gebruikt met Java 8 en hoger. Bovendien is het compatibel met JUnit Rules API.

Laten we eerst de maven-afhankelijkheid voor de kernfunctionaliteit definiëren:

 org.testcontainers testcontainers 1.11.4 

Er zijn ook modules voor gespecialiseerde containers. In deze tutorial gebruiken we PostgreSQL en Selenium.

Laten we de relevante afhankelijkheden toevoegen:

 org.testcontainers postgresql 1.11.4 org.testcontainers selenium 1.11.4 

We kunnen de nieuwste versies vinden op Maven Central.

We hebben ook Docker nodig om containers uit te voeren. Raadpleeg de Docker-documentatie voor installatie-instructies.

Zorg ervoor dat u Docker-containers in uw testomgeving kunt uitvoeren.

3. Gebruik

Laten we een generieke containerregel configureren:

@ClassRule openbare statische GenericContainer simpleWebServer = nieuwe GenericContainer ("alpine: 3.2") .withExposedPorts (80) .withCommand ("/ bin / sh", "-c", "hoewel waar; echo" + "\" HTTP / 1.1 200 OK \ n \ nHallo wereld! \ "| Nc -l -p 80; klaar");

We construeren een GenericContainer testregel door de naam van een docker-afbeelding op te geven. Vervolgens configureren we het met builder-methoden:

  • We gebruiken withExposedPorts om een ​​poort uit de container bloot te leggen
  • withCommand definieert een containeropdracht. Het wordt uitgevoerd wanneer de container start.

De regel is geannoteerd met @ClassRule. Als gevolg hiervan wordt de Docker-container gestart voordat een test in die klasse wordt uitgevoerd. De container wordt vernietigd nadat alle methoden zijn uitgevoerd.

Als je solliciteert @Regel annotatie, GenericContainer regel start een nieuwe container voor elke testmethode. En het stopt de container wanneer die testmethode is voltooid.

We kunnen IP-adres en poort gebruiken om te communiceren met het proces dat in de container wordt uitgevoerd:

@Test openbare ongeldige gegevenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse () genereert uitzondering {String address = "//" + simpleWebServer.getContainerIpAddress () + ":" + simpleWebServer.getMappedPort (80); String response = simpleGetRequest (adres); assertEquals (antwoord, "Hallo wereld!"); }

4. Gebruiksmodi

Er zijn meerdere gebruiksmodi van de testcontainers. We zagen een voorbeeld van het uitvoeren van een GenericContainer.

TestContainers bibliotheek heeft ook regeldefinities met gespecialiseerde functionaliteit. Ze zijn voor containers met veelgebruikte databases zoals MySQL, PostgreSQL; en anderen houden van webclients.

Hoewel we ze als generieke containers kunnen uitvoeren, bieden de specialisaties uitgebreide gemaksmethoden.

4.1. Databases

Laten we aannemen dat we een databaseserver nodig hebben voor integratietests op de datatoegangslaag. We kunnen databases in containers draaien met behulp van de TestContainers-bibliotheek.

We starten bijvoorbeeld een PostgreSQL-container op met PostgreSQLContainer regel. Vervolgens kunnen we hulpmethoden gebruiken. Dit zijn getJdbcUrl, getUsername, getPassword voor databaseverbinding:

@Rule openbaar PostgreSQLContainer postgresContainer = nieuwe PostgreSQLContainer (); @Test openbare leegte whenSelectQueryExecuted_thenResulstsReturned () gooit uitzondering {String jdbcUrl = postgresContainer.getJdbcUrl (); String gebruikersnaam = postgresContainer.getUsername (); String wachtwoord = postgresContainer.getPassword (); Connection conn = DriverManager .getConnection (jdbcUrl, gebruikersnaam, wachtwoord); ResultSet resultSet = conn.createStatement (). ExecuteQuery ("SELECT 1"); resultSet.next (); int resultaat = resultSet.getInt (1); assertEquals (1, resultaat); }

Het is ook mogelijk om PostgreSQL als generieke container uit te voeren. Maar het zou moeilijker zijn om de verbinding te configureren.

4.2. Webstuurprogramma's

Een ander handig scenario is om containers met webbrowsers uit te voeren. BrowserWebDriverContainer regel maakt hardlopen mogelijk Chrome en Firefox in docker-selenium containers. Vervolgens beheren we ze met RemoteWebDriver.

Dit is erg handig voor het automatiseren van UI / Acceptatietests voor webapplicaties:

@Rule openbare BrowserWebDriverContainer chrome = nieuwe BrowserWebDriverContainer () .withCapabilities (nieuwe ChromeOptions ()); @Test openbare leegte whenNavigatedToPage_thenHeadingIsInThePage () {RemoteWebDriver-stuurprogramma = chrome.getWebDriver (); driver.get ("// example.com"); String heading = driver.findElement (By.xpath ("/ html / body / div / h1")) .getText (); assertEquals ("Voorbeelddomein", kop); }

4.3. Docker Compose

Als de tests complexere services vereisen, kunnen we deze specificeren in een docker-compose het dossier:

simpleWebServer: image: alpine: 3.2 commando: ["/ bin / sh", "-c", "hoewel waar; echo 'HTTP / 1.1 200 OK \ n \ nHallo wereld!' | nc -l -p 80; klaar "]

Vervolgens gebruiken we DockerComposeContainer regel. Deze regel start en voert services uit zoals gedefinieerd in het opstelbestand.

We gebruiken getServiceHost en getServicePost methoden om een ​​verbindingsadres met de service op te bouwen:

@ClassRule openbare statische DockerComposeContainer compose = nieuwe DockerComposeContainer (nieuw bestand ("src / test / resources / test-compose.yml")) .withExposedService ("simpleWebServer_1", 80); @Test openbare leegte gegevenSimpleWebServerContainer_whenGetReuqest_thenReturnsResponse () gooit uitzondering {String address = "//" + compose.getServiceHost ("simpleWebServer_1", 80) + ":" + compose.getServicePort ("simpleWebServer_1", 80); String response = simpleGetRequest (adres); assertEquals (antwoord, "Hallo wereld"); }

5. Conclusie

We hebben gezien hoe we het konden gebruiken TestContainers bibliotheek. Het vereenvoudigt het ontwikkelen en uitvoeren van integratietests.

We gebruikten GenericContainer regel voor containers met opgegeven docker-images. Toen keken we naar PostgreSQLContainer, BrowserWebDriverContainer en DockerComposeContainer reglement. Ze bieden meer functionaliteit voor specifieke gebruiksscenario's.

Ten slotte zijn hier codevoorbeelden te vinden op GitHub.