Skip to content

Commit 8d76cfb

Browse files
committed
Initial commit
0 parents  commit 8d76cfb

File tree

9 files changed

+353
-0
lines changed

9 files changed

+353
-0
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Example of Maven project using Docker plugin for integration testing on real databases
2+
3+
When you test applications performing queries on a database, it's not always possible to rely on mocks or embedded databases (e.g. H2): sometimes you need to execute the application in an environment as similar as possible to the production one. In this situations using Docker could be a good idea.
4+
5+
This example shows a Maven project using the [docker-maven-plugin](https://github.com/fabric8io/docker-maven-plugin) for testing a SQL query both on MariaDB and PostgreSQL databases.
6+
7+
## How it works
8+
9+
During the `pre-integration-test` phase the plugin starts 2 Docker images (one for MariaDB and one for PostgreSQL).
10+
11+
Inside the `src/test/docker` directory there are 2 SQL files used to create an example table on both databases. The plugin copies these files in the `docker-entrypoint-initdb.d` directory inside each Docker image. This directory is used by [both](https://hub.docker.com/_/mariadb/) [images](https://hub.docker.com/_/postgres/) for performing custom initialization.
12+
13+
The plugin is also configured to wait until the databases are up and running (listening on their default ports).
14+
15+
The plugin sets the IP address of the running image inside a Maven property having the following format: `docker.container.<image-alias>.ip`. In this way it is possible to fill the configuration files inside the `src/test/resources` directory using Maven properties filtering. Thus, it is possible to read the proper connection configuration from the `IntegrationTest` class.
16+
17+
Please, have a look to the pom.xml and the other files: there are some additional tips and information contained in the comments.
18+
19+
## How to debug the integration test
20+
21+
mvn -Dmaven.failsafe.debug verify

pom.xml

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>net.zonia3000</groupId>
6+
<artifactId>maven-docker-database-testing</artifactId>
7+
<version>1.0</version>
8+
9+
<packaging>jar</packaging>
10+
11+
<properties>
12+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
13+
<maven.compiler.source>1.8</maven.compiler.source>
14+
<maven.compiler.target>1.8</maven.compiler.target>
15+
16+
<mariadb.password>mariadbtest</mariadb.password>
17+
<postgresql.password>pgsqltest</postgresql.password>
18+
</properties>
19+
20+
<dependencies>
21+
<dependency>
22+
<groupId>mysql</groupId>
23+
<artifactId>mysql-connector-java</artifactId>
24+
<version>5.1.37</version>
25+
<scope>runtime</scope>
26+
</dependency>
27+
<dependency>
28+
<groupId>org.postgresql</groupId>
29+
<artifactId>postgresql</artifactId>
30+
<version>9.3-1104-jdbc41</version>
31+
<scope>runtime</scope>
32+
</dependency>
33+
<dependency>
34+
<groupId>junit</groupId>
35+
<artifactId>junit</artifactId>
36+
<version>4.12</version>
37+
<scope>test</scope>
38+
</dependency>
39+
</dependencies>
40+
41+
<build>
42+
<plugins>
43+
<plugin>
44+
<groupId>io.fabric8</groupId>
45+
<artifactId>docker-maven-plugin</artifactId>
46+
<version>0.26.0</version>
47+
48+
<configuration>
49+
<!-- URL to Docker daemon -->
50+
<dockerHost>http://localhost:2375</dockerHost>
51+
52+
<!-- Configured Docker images -->
53+
<images>
54+
55+
<!-- MariaDB image -->
56+
<image>
57+
<name>test-mariadb</name>
58+
<alias>test-mariadb</alias>
59+
<build>
60+
<from>mariadb:10.3</from>
61+
<assembly>
62+
<mode>dir</mode>
63+
<!-- database startup script -->
64+
<targetDir>/docker-entrypoint-initdb.d</targetDir>
65+
<inline>
66+
<files>
67+
<file>
68+
<source>src/test/docker/setup-mariadb.sql</source>
69+
</file>
70+
</files>
71+
</inline>
72+
</assembly>
73+
<env>
74+
<MYSQL_ROOT_PASSWORD>${mariadb.password}</MYSQL_ROOT_PASSWORD>
75+
</env>
76+
</build>
77+
<run>
78+
<!-- Wait for database up and running -->
79+
<wait>
80+
<tcp>
81+
<ports>
82+
<port>3306</port>
83+
</ports>
84+
</tcp>
85+
</wait>
86+
</run>
87+
</image>
88+
89+
<!-- PostgreSQL image -->
90+
<image>
91+
<name>test-postgres</name>
92+
<alias>test-postgres</alias>
93+
<build>
94+
<from>postgres:10.4</from>
95+
<assembly>
96+
<mode>dir</mode>
97+
<!-- database startup script -->
98+
<targetDir>/docker-entrypoint-initdb.d</targetDir>
99+
<inline>
100+
<files>
101+
<file>
102+
<source>src/test/docker/setup-postgres.sql</source>
103+
</file>
104+
</files>
105+
</inline>
106+
</assembly>
107+
<env>
108+
<POSTGRES_PASSWORD>${postgresql.password}</POSTGRES_PASSWORD>
109+
</env>
110+
</build>
111+
<run>
112+
<!-- Wait for database up and running -->
113+
<wait>
114+
<tcp>
115+
<ports>
116+
<port>5432</port>
117+
</ports>
118+
</tcp>
119+
</wait>
120+
</run>
121+
</image>
122+
</images>
123+
124+
<!-- If we want to skip tests we should also skip Docker plugin execution -->
125+
<skip>${maven.test.skip}</skip>
126+
</configuration>
127+
128+
<executions>
129+
<execution>
130+
<!-- start Docker -->
131+
<id>start</id>
132+
<phase>pre-integration-test</phase>
133+
<goals>
134+
<goal>build</goal>
135+
<goal>start</goal>
136+
</goals>
137+
</execution>
138+
<execution>
139+
<!-- stop Docker -->
140+
<id>stop</id>
141+
<phase>post-integration-test</phase>
142+
<goals>
143+
<goal>stop</goal>
144+
</goals>
145+
</execution>
146+
</executions>
147+
</plugin>
148+
149+
<!-- maven-surefire-plugin executes unit tests. We need to exclude the IntegrationTest class here -->
150+
<plugin>
151+
<groupId>org.apache.maven.plugins</groupId>
152+
<artifactId>maven-surefire-plugin</artifactId>
153+
<version>2.22.0</version>
154+
<configuration>
155+
<excludes>
156+
<exclude>**/IntegrationTest.java</exclude>
157+
</excludes>
158+
</configuration>
159+
</plugin>
160+
161+
<!-- maven-failsafe-plugin executes integration tests. We need to include the IntegrationTest class here -->
162+
<plugin>
163+
<groupId>org.apache.maven.plugins</groupId>
164+
<artifactId>maven-failsafe-plugin</artifactId>
165+
<version>2.22.0</version>
166+
<configuration>
167+
<includes>
168+
<include>**/IntegrationTest.java</include>
169+
</includes>
170+
<trimStackTrace>false</trimStackTrace>
171+
</configuration>
172+
<executions>
173+
<execution>
174+
<goals>
175+
<goal>integration-test</goal>
176+
<goal>verify</goal>
177+
</goals>
178+
</execution>
179+
</executions>
180+
</plugin>
181+
182+
<!-- We apply Maven filtering on test resources (see <testResources> element) -->
183+
<plugin>
184+
<groupId>org.apache.maven.plugins</groupId>
185+
<artifactId>maven-resources-plugin</artifactId>
186+
<version>3.1.0</version>
187+
<executions>
188+
<execution>
189+
<id>filter-resources</id>
190+
<phase>pre-integration-test</phase>
191+
<goals>
192+
<goal>testResources</goal>
193+
</goals>
194+
</execution>
195+
</executions>
196+
</plugin>
197+
</plugins>
198+
199+
<!-- Enabling the filtering on test resources we can dynamically fill the properties files from Maven properties -->
200+
<testResources>
201+
<testResource>
202+
<directory>src/test/resources</directory>
203+
<includes>
204+
<include>**/*.properties</include>
205+
</includes>
206+
<filtering>true</filtering>
207+
</testResource>
208+
</testResources>
209+
</build>
210+
</project>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package net.zonia3000.example;
2+
3+
import java.sql.Connection;
4+
import java.sql.DriverManager;
5+
import java.sql.ResultSet;
6+
import java.sql.SQLException;
7+
import java.sql.Statement;
8+
import java.util.Properties;
9+
10+
/**
11+
* Performs a SELECT query providing the value contained into the example table.
12+
*
13+
* @author zonia3000
14+
*/
15+
public class DBValueSelector {
16+
17+
private final Properties config;
18+
19+
/**
20+
* @param config Properties defining the configuration necessary for setting
21+
* up the connection to the database.
22+
*/
23+
public DBValueSelector(Properties config) {
24+
this.config = config;
25+
}
26+
27+
/**
28+
* @return the value contained in example table.
29+
* @throws SQLException
30+
*/
31+
public String getValue() throws SQLException {
32+
33+
String sql = "SELECT value FROM example";
34+
35+
try (Connection conn = DriverManager.getConnection(config.getProperty("url"),
36+
config.getProperty("user"), config.getProperty("password"));
37+
Statement stat = conn.createStatement();
38+
ResultSet rs = stat.executeQuery(sql)) {
39+
40+
if (rs.next()) {
41+
return rs.getString(1);
42+
}
43+
}
44+
45+
return null;
46+
}
47+
}

src/test/docker/setup-mariadb.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE DATABASE test;
2+
3+
USE test;
4+
5+
CREATE TABLE example (value VARCHAR(255));
6+
7+
INSERT INTO example(value) VALUES ('Hello from MariaDB!');

src/test/docker/setup-postgres.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE TABLE example (value VARCHAR);
2+
3+
INSERT INTO example(value) VALUES ('Hello from PostgreSQL!');
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package net.zonia3000.example;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.util.Properties;
6+
import org.junit.Test;
7+
import static org.junit.Assert.*;
8+
9+
/**
10+
* Tests the DBValueSelector on MariaDB and PostgreSQL.
11+
*
12+
* @author zonia3000
13+
*/
14+
public class IntegrationTest {
15+
16+
@Test
17+
public void testMariaDB() throws Exception {
18+
String value = new DBValueSelector(getProperties("mariadb-config.properties")).getValue();
19+
assertEquals("Hello from MariaDB!", value);
20+
}
21+
22+
@Test
23+
public void testPostgreSQL() throws Exception {
24+
String value = new DBValueSelector(getProperties("postgres-config.properties")).getValue();
25+
assertEquals("Hello from PostgreSQL!", value);
26+
}
27+
28+
/**
29+
* Creates a Properties instance reading a file located in
30+
* src/test/resources.
31+
*/
32+
private static Properties getProperties(String fileName) throws IOException {
33+
Properties properties = new Properties();
34+
try (InputStream in = IntegrationTest.class.getClassLoader().getResourceAsStream(fileName)) {
35+
properties.load(in);
36+
}
37+
return properties;
38+
}
39+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package net.zonia3000.example;
2+
3+
import org.junit.Test;
4+
import static org.junit.Assert.*;
5+
6+
/**
7+
* This useless UnitTest class is provided to show that if you have both unit
8+
* test and integration test classes you need to configure the
9+
* maven-surefire-plugin in order to exclude the integration test ones (see
10+
* pom.xml).
11+
*
12+
* @author zonia3000
13+
*/
14+
public class UnitTest {
15+
16+
@Test
17+
public void fakeTest() {
18+
assertTrue(true);
19+
}
20+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
url=jdbc:mysql://${docker.container.test-mariadb.ip}:3306/test
2+
user=root
3+
password=${mariadb.password}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
url=jdbc:postgresql://${docker.container.test-postgres.ip}:5432/postgres
2+
user=postgres
3+
password=${postgresql.password}

0 commit comments

Comments
 (0)