A presentation at Magdeburger Developer Days in May 2019 in Magdeburg, Germany by Philipp Krenn
Richtige Integrationstests mit Containern Philipp Krenn @xeraa
Developer
Tests
But the unit tests passed, so… https://twitter.com/Aaronius/status/ 933497253347463168
Integration Tests
Mocks
Mockito, EasyMock, JMock,…
Ich mock mir die Welt widdewidde wie sie mir gefällt
https://www.monkeyuser.com/2018/ happy-flow/
! Unit tests, systems not under your control ! Test real datastore
In-Memory
H2, HSQLDB, Apache Derby,…
Embedded Elasticsearch unsupported in 5.0+ https://www.elastic.co/blog/elasticsearch-the-server
! Often good enough ! Test real datastore, supported systems
Actual Datastore
Local installation Docker container Cloud
Demo
! “Good old approach” ! External dependency, parallelization
Embedded
embedded-elasticsearch https://github.com/allegro/embedded-elasticsearch
Customization & Mappings .withPlugin(“analysis-stempel”) .withIndex(“cars”, IndexSettings.builder() .withType(“_doc”, getSystemResourceAsStream(“car-mapping.json”))
! IDE support, customization, custom lifecycle ! Custom integration
More embedded datastores https://github.com/flapdoodle-oss/ de.flapdoodle.embed.process
Build Tool
docker-maven-plugin http://dmp.fabric8.io
Dockerfile or Docker assembly <build> <from>java:8</from> <assembly> <descriptor>docker-assembly.xml</descriptor> </assembly> <cmd> <shell>java -jar /maven/service.jar</shell> </cmd> </build>
Build a custom image: docker:build Run container: docker:start docker:stop
maven-failsafe-plugin https://maven.apache.org/surefire/maven-failsafe-plugin/
! Standard or custom Docker image ! One instance for all tests, no IDE support
Testcontainers Generic
Dependency @ClassRule public static GenericContainer redis = new GenericContainer(“redis:5.0.5”) .withExposedPorts(6379);
Docker Compose integration @ClassRule public static DockerComposeContainer environment = new DockerComposeContainer(new File(“src/test/resources/compose.yml”)) .withExposedService(“elasticsearch_1”, ELASTICSEARCH_PORT, Wait.forHttp(“/”).forStatusCode(200));
What’s in docker ps -a
Docker for Mac API: socat Linux: Multipurpose relay (SOcket CAT) https://github.com/alpine-docker/socat
Cleanup: Moby Ryuk https://github.com/testcontainers/moby-ryuk
[Ryuk] drops a Death Note, a notebook that allows the user to kill anyone simply by knowing their name and face https://en.wikipedia.org/wiki/Ryuk_(Death_Note)
! IDE support, customization, custom lifecycle ! Hacky configuration
Testcontainers Custom
ElasticsearchContainer https://www.testcontainers.org/modules/elasticsearch/
More languages Scala, Go, .net , Python , JavaScript , Rust * * * Early development * *
Selenium 2 / Webdriver VNC screen recording
Inside Containers
Wormhole Pattern
$ docker run -it —rm -v $PWD:$PWD -w $PWD -v /var/run/docker.sock:/var/run/docker.sock maven:3 mvn —projects parent,4_testcontainers-custom test $ docker ps -a
Conclusion
Why Integration Tests
Why not Mocking In-Memory Actual Datastore
How Embedded Build Tool Testcontainers
Code https://github.com/xeraa/integration-test-demo
Questions? Philipp Krenn @xeraa