Demonstrate how to use docker-maven-plugin
to fire up a MongoDB container to be used during integration tests.
Note: With Spring Boot 1.5 you could use @DataMongoTest
with the embedded MongoDB, but this is not the point here.
First: Configure docker-maven-plugin
with the containers you need, here: mongodb:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.20.1</version>
<configuration>
<!-- Those are the containers you want to run
no need to configure ports yet -->
<images>
<image>
<name>mongo:3.2.9</name>
<alias>mongo-db</alias>
<run>
<!-- Tells the plugin to wait for a log entry for 60s max. -->
<wait>
<log>waiting for connections on port 27017</log>
<time>60000</time>
</wait>
</run>
</image>
</images>
</configuration>
<!-- Configure the execution of the plugin itself -->
<executions>
<execution>
<id>prepare-it-database</id>
<!-- During this phase… -->
<phase>pre-integration-test</phase>
<!-- …run the start goal -->
<goals>
<goal>start</goal>
</goals>
<configuration>
<images>
<image>
<alias>mongo-db</alias>
<run>
<!-- Here we need to configure the ports, the
Mongo image offers 27018, we tell the plugin
to map it onto a random local free port -->
<ports>
<!-- Maps the random port
onto a Maven property -->
<port>mongo-db-it.port:27017</port>
</ports>
</run>
</image>
</images>
</configuration>
</execution>
<execution>
<id>remove-it-database</id>
<!-- Stop the containers after integration test -->
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
No tests are executed yet. I prefer the maven-failsafe-plugin
for executing integration tests. maven-failsafe-plugin
makes sure that a pre and post phase are executed. It also offers the possiblity to push any maven property into the vm environment which we do now with the generated property mongo-db-it.port
from the docker-maven-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<environmentVariables>
<!-- Push the Maven property into the environment under the given name (here: spring.data.mongodb.port) -->
<spring.data.mongodb.port>${mongo-db-it.port}</spring.data.mongodb.port>
</environmentVariables>
</configuration>
</plugin>
You can push the whole connectstring into your enviroment.
As we are using Spring Boot here, the integration test SomeDocumentRepositoryIT
is pretty simple:
@ExtendWith(SpringExtension.class)
@DataMongoTest
public class SomeDocumentRepositoryIT {
private static final Logger LOG = LoggerFactory
.getLogger(SomeDocumentRepositoryIT.class);
@Autowired
private SomeDocumentRepository someDocumentRepository;
@Autowired
private MongoTemplate mongoTemplate;
@Test
public void doSomething() {
someDocumentRepository.deleteAll();
final SomeDocument d = someDocumentRepository.save(new SomeDocument("foobar"));
LOG.info("Stored document with id {}", d.getId());
final SomeDocument d2 = mongoTemplate.findById(d.getId(), SomeDocument.class);
assertThat(d2.getValue(), is("foobar"));
}
}
The property spring.data.mongodb.port
is automatically picked up from the enviroment with higher priority than configuration files so the test runs agains our container.