Using docker-compose-gradle-plugin for integration tests
authorGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 25 Dec 2016 23:10:29 +0000 (00:10 +0100)
committerGustavo Martin Morcuende <gu.martinm@gmail.com>
Sun, 25 Dec 2016 23:10:29 +0000 (00:10 +0100)
SpringJava/Gradle/spring-jpa-persistence/build.gradle
SpringJava/Gradle/spring-jpa-persistence/src/integTest/java/de/spring/example/persistence/repository/AdDescriptionRepositoryDockerComposeRuleShould.java [new file with mode: 0644]
SpringJava/Gradle/spring-jpa-persistence/src/integTest/java/de/spring/example/persistence/repository/AdDescriptionRepositoryShould.java
SpringJava/Gradle/spring-jpa-persistence/src/integTest/resources/docker/docker-compose.yml
SpringJava/Gradle/spring-jpa-persistence/src/integTest/resources/spring-configuration-docker-test/datasource-test-configuration.xml
SpringJava/Gradle/spring-jpa-persistence/src/main/resources/spring-configuration/liquibase/ddlChangelog.xml

index 1c8882c..ed6e4d1 100644 (file)
@@ -8,7 +8,8 @@ buildscript {
         maven { url 'https://plugins.gradle.org/m2/' }
     }
     dependencies {
-        classpath "gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.7"
+        classpath 'gradle.plugin.com.ewerk.gradle.plugins:querydsl-plugin:1.0.7'
+        classpath 'com.avast.gradle:docker-compose-gradle-plugin:0.3.16'
     }
 }
 
@@ -17,6 +18,7 @@ apply plugin: 'eclipse'
 apply plugin: 'idea'
 apply plugin: 'jacoco'
 apply plugin: 'com.ewerk.gradle.plugins.querydsl'
+apply plugin: 'docker-compose'
 
 
 targetCompatibility = 1.8
@@ -109,6 +111,20 @@ dependencies {
     testCompile('com.h2database:h2:1.4.193')
     // or MYSQL with docker :)
     testCompile('mysql:mysql-connector-java:6.0.5')
+
+       // DockerComposeRule DOES NOT WORK FOR THESE REASONS:
+       // 1. Spring context is loaded before the DockerComposeRule
+       // 2. DockerComposeRule can work with random ports, the problem is:
+       // the Spring Context was loaded before DockerComposeRule and dataSource
+       // requires some port for connection to data base.
+
+       // These issues can be fixed using org.junit.Suite and running
+       // DockerComposeRule in the Suite instead of in every Test.
+       // But if I want to run just one test that solution does not work because
+       // DockerComposeRule will be declared in the Suite instead of in the Test.
+       // We will have to run our tests always from the Suite not being able to run
+       // just one Test from the IDE :(
+       // See: AdDescriptionRepositoryDockerComposeRuleShould
     testCompile 'com.palantir.docker.compose:docker-compose-rule:0.28.1'
 }
 
@@ -150,6 +166,24 @@ task integTest(type: Test) {
     // mustRunAfter test
 }
 
+integTest.doFirst {
+       // It is required in order to run data bases in random ports.
+       // We need it for running tests from IDE and from command console but
+       // also it will be required by systems like Travis where we do not control
+       // the available ports.
+       def mysqlInfo = dockerCompose.servicesInfos.mysql
+       systemProperty 'DATABASE_PORT', mysqlInfo.ports[3306]
+}
+
+dockerCompose.isRequiredBy(integTest)
+dockerCompose {
+    useComposeFiles = ['src/integTest/resources/docker/docker-compose.yml']
+    captureContainersOutput = false
+    stopContainers = true
+    removeContainers = true
+    buildBeforeUp = false
+}
+
 querydsl {
   library = 'com.querydsl:querydsl-apt:4.1.3'
   querydslSourcesDir = "$buildDir/generated-sources/querydsl"
diff --git a/SpringJava/Gradle/spring-jpa-persistence/src/integTest/java/de/spring/example/persistence/repository/AdDescriptionRepositoryDockerComposeRuleShould.java b/SpringJava/Gradle/spring-jpa-persistence/src/integTest/java/de/spring/example/persistence/repository/AdDescriptionRepositoryDockerComposeRuleShould.java
new file mode 100644 (file)
index 0000000..bc53430
--- /dev/null
@@ -0,0 +1,61 @@
+package de.spring.example.persistence.repository;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+import javax.inject.Inject;
+
+import org.junit.ClassRule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.palantir.docker.compose.DockerComposeRule;
+import com.palantir.docker.compose.connection.waiting.HealthChecks;
+
+import de.spring.example.persistence.domain.AdDescription;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration( {"classpath*:spring-configuration/*.xml",
+       "classpath*:spring-configuration-docker-test/*.xml"} )
+@Transactional
+
+// IT DOES NOT WORK FOR THESE REASONS:
+// 1. Spring context is loaded before the DockerComposeRule
+// 2. DockerComposeRule can work with random ports, the problem is:
+// the Spring Context was loaded before DockerComposeRule and dataSource
+// requires some port for connection to data base.
+
+// These issues can be fixed using org.junit.Suite and running
+// DockerComposeRule in the Suite instead of in every Test.
+// But if I want to run just one test that solution does not work because
+// DockerComposeRule will be declared in the Suite instead of in the Test.
+// We will have to run our tests always from the Suite not being able to run
+// just one Test from the IDE :(
+@Ignore
+public class AdDescriptionRepositoryDockerComposeRuleShould {
+       
+       @Inject
+       AdDescriptionRepository adDescriptionRepository;
+
+       @ClassRule
+    public static final DockerComposeRule DOCKER = DockerComposeRule.builder()
+            .file("src/integTest/resources/docker/docker-compose.yml")
+            .waitingForService("mysql", HealthChecks.toHaveAllPortsOpen())
+            .saveLogsTo("build/dockerLogs")
+            .build();
+       
+       @Test public void
+       find_ad_descriptions_by_ad() {
+               Iterable<AdDescription> adDescriptions = adDescriptionRepository.findAll();
+               
+               for (AdDescription adDescription : adDescriptions) {
+                       assertThat(adDescription, is(notNullValue()));
+               }
+       }
+       
+}
index ffaa3ad..081704f 100644 (file)
@@ -1,17 +1,17 @@
 package de.spring.example.persistence.repository;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
 import javax.inject.Inject;
 
-import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.test.context.ContextConfiguration;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.transaction.annotation.Transactional;
 
-import com.palantir.docker.compose.DockerComposeRule;
-import com.palantir.docker.compose.connection.waiting.HealthChecks;
-
 import de.spring.example.persistence.domain.AdDescription;
 
 @RunWith(SpringJUnit4ClassRunner.class)
@@ -22,20 +22,14 @@ public class AdDescriptionRepositoryShould {
        
        @Inject
        AdDescriptionRepository adDescriptionRepository;
-
-       @ClassRule
-    public static final DockerComposeRule DOCKER = DockerComposeRule.builder()
-            .file("src/integTest/resources/docker/docker-compose.yml")
-            .waitingForService("mysql", HealthChecks.toHaveAllPortsOpen())
-            .saveLogsTo("build/dockerLogs")
-            .build();
        
        @Test public void
        find_ad_descriptions_by_ad() {
                Iterable<AdDescription> adDescriptions = adDescriptionRepository.findAll();
                
-               Iterable<AdDescription> lol = adDescriptions;
-               
+               for (AdDescription adDescription : adDescriptions) {
+                       assertThat(adDescription, is(notNullValue()));
+               }
        }
        
 }
index 4296799..1a9df2e 100644 (file)
         -->\r
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">\r
                <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />\r
-               <property name="url" value="jdbc:mysql://127.0.0.1:3737/mybatis_example?createDatabaseIfNotExist=true&amp;allowMultiQueries=true&amp;autoReconnect=true&amp;characterEncoding=UTF-8" />\r
+\r
+               <!-- DATABASE_PORT should be a system or environment property\r
+                        If running tests from the IDE, we must configure JUnit for using\r
+                        this property with the right value.\r
+\r
+                        It is useful if we want to run just one test from our IDE but it requires\r
+                        to have a database always running.\r
+\r
+                        There is no collision with gradle integTest command because docker-compose is using\r
+                        a random port. So we can run tests one by one from our IDE (but it requires database running)\r
+                        and also run our tests from the command console by means of gradle integTest (it will\r
+                        start a new data base in a random and available port)\r
+                        This feature is also required by systems like Travis where we do not control the available ports.\r
+                -->\r
+               <property name="url" value="jdbc:mysql://127.0.0.1:{DATABASE_PORT}/mybatis_example?createDatabaseIfNotExist=true&amp;allowMultiQueries=true&amp;autoReconnect=true&amp;characterEncoding=UTF-8" />\r
                <property name="username" value="root" />\r
                <property name="password" value="root" />\r
        </bean>\r
index 2fd98a8..5c53eb9 100644 (file)
@@ -35,7 +35,7 @@
             <column defaultValueComputed="CURRENT_TIMESTAMP" name="CREATED_AT" type="TIMESTAMP">
                 <constraints nullable="false"/>
             </column>
-            <column defaultValue="0000-00-00 00:00:00" name="UPDATED_AT" type="TIMESTAMP">
+            <column defaultValue="1970-01-01 00:00:01" name="UPDATED_AT" type="TIMESTAMP">
                 <constraints nullable="false"/>
             </column>
         </createTable>