Integration testing with
TestСontainers and JUnit 5
Nikolay Kuznetsov
@nikolayk812
Helsinki JUG
Zalando
9 December 2019
Slide 2
Slide 2 text
About me
● Go developer at Zalando Wardrobe
● 6+ years of Java experience
● Conference speaker:
○ Voxxed Days Cluj, Container Days Hamburg
● TestContainers-Go contributor
Slide 3
Slide 3 text
Why integration testing?
Slide 4
Slide 4 text
2 unit tests, 0 integration tests
Slide 5
Slide 5 text
Basic integration test
Slide 6
Slide 6 text
Trade-offs
Test Runtime
Slide 7
Slide 7 text
Integration testing evolution
● In-memory mocking
● Local DBs
● Vagrant
● Docker / Docker Compose
● Docker API
Slide 8
Slide 8 text
Docker advantages
● 100% compatible database
● Same version as production
● Empty or known state
Slide 9
Slide 9 text
Docker architecture
Slide 10
Slide 10 text
How to start a container for test?
● Shell scripts
● Maven plugin
● Docker Compose
● Docker API
● MiniKube, Kubernetes
JUnit 5 extension logic
● Implement interface(s) from o.j.j.api.extension package
○ i.e. BeforeEachCallback, ExecutionCondition
● Register with @ExtendsWith annotation
● See @Testcontainers for reference
Slide 34
Slide 34 text
TestContainers modules
● Preconfigured, optimized for testing
● Wrappers on top of GenericContainer class
● 14 databases
● MockServer, LocalStack, Kafka, ToxiProxy
Slide 35
Slide 35 text
Demo-2: setup
User Service
Slide 36
Slide 36 text
Demo-2: Docker network
User Service
user-alias: 8083 postgres-alias: 5432
localhost: 32812
Slide 37
Slide 37 text
Demo-2: scenario
User Service
POST /users
GET /user/
Slide 38
Slide 38 text
Demo-2
github.com/nikolayk812/hjug-tc-demo
Slide 39
Slide 39 text
Demo-2: recap
● Docker network and alias
Slide 40
Slide 40 text
Why end-to-end testing?
● Business flows across multiple services
● Regression, when
○ + new service
○ - legacy service
Slide 41
Slide 41 text
Some cluster
Spring Cloud
Kubernetes
Slide 42
Slide 42 text
E2E strategies
● Against a deployed cluster
● Against on-demand in memory cluster
Slide 43
Slide 43 text
Deployed cluster cons
● Replace a service with a newer version => instability
● Temporary service name => non-discoverable
● Unexpected databases states
○ Care to clear data after the test?
Slide 44
Slide 44 text
On-demand cluster cons
● Time to start all containers
● Memory + CPU
● How actually to create it?
Slide 45
Slide 45 text
On-demand Kubernetes for E2E?
Slide 46
Slide 46 text
YAGNI
Slide 47
Slide 47 text
On-demand cluster TC approach
● Each service started by TestContainers
● Shared Docker network
● Functional tests
● Unless testing Kubernetes manifests
Slide 48
Slide 48 text
E2E setup
User Service
Item Service
Slide 49
Slide 49 text
Hints
● Host port forwarding
Testcontainers.exposeHostPorts()
● Fixed host port (for remote debugging)
GenericContainer.addFixedExposedPort()
● Reusable containers
github.com/testcontainers/testcontainers-java/issues/781
Slide 50
Slide 50 text
Takeaways
● https://testcontainers.org
● Balance between flexibility, speed and features
● Works on Mac, Linux, Windows
● Great for integration tests!
● Possible to use for end-to-end tests