Wednesday, November 7, 2007

Maven2 cargo plugin and integration test

So I was facing a problem of creating Maven2 project that would:
  1. Create domain based on JBoss default server configuration,
  2. Copy to this newly created domain configuration file and datasource configuration,
  3. Start container with domain that was result of #2.
I thought that cargo-maven2-plugin will do the job.
Unfortunately it didn't.

My initial approach was:
  1. Attach cargo:configure (undocumented goal :-/) to generate-test-sources phase, using standalone type, so configuration gets generated from scratch based on default,
  2. Attach antrun:run to generate-test-resources phase to copy .properties to conf, and -ds.xml to deploy,
  3. Attach cargo:start to pre-integration-test phase, using existing type, so configuration from #2 is read-only used, and *should* not be overwritten.
In theory it seems all great and already working.
But I couldn't convince cargo to work like that.
Started executing maven with -X to discover that maven configures mojos properly, not a big surprise, especially if you take a look at CI of cargo, you would suspect cargo of errors.
At the end of a day I created this ugly but working configuration:



<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/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>your.group.id</groupId>
 <artifactId>itest</artifactId>
 <version>0.1-SNAPSHOT</version>
 <name>Integration Tests</name>
 <description>This module provides a collection of integration tests.</description>
 <packaging>jar</packaging>
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>your.group.id</groupId>
   <artifactId>your-ear</artifactId>
   <type>ear</type>
   <version>${project.version}</version>
  </dependency>
  <dependency>
   <groupId>org.codehaus.cargo</groupId>
   <artifactId>cargo-ant</artifactId>
   <version>0.9</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.codehaus.cargo</groupId>
   <artifactId>cargo-core-uberjar</artifactId>
   <version>0.9</version>
   <scope>test</scope>
  </dependency>
 </dependencies>
 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <executions>
     <execution>
      <phase>integration-test</phase>
      <goals>
       <goal>test</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
   <plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.1</version>
    <executions>
     <execution>
      <id>tune-deployment</id>
      <phase>generate-test-resources</phase>
      <goals>
       <goal>run</goal>
      </goals>
      <configuration>
       <tasks>
        <copy todir="${basedir}/target/jboss4x" overwrite="true">
         <fileset dir="${basedir}/src/jboss4x"/>
        </copy>
       </tasks>
      </configuration>
     </execution>
     <!-- This execution is needed to start container with existing configuration -->
     <execution>
      <id>start-container</id>
      <phase>pre-integration-test</phase>
      <goals>
       <goal>run</goal>
      </goals>
      <configuration>
       <tasks>
        <taskdef resource="cargo.tasks">
         <classpath refid="maven.test.classpath"/>
        </taskdef>
        <echo message="Starting Cargo..."/>
        <cargo containerId="jboss4x"
            home="${jboss4x.home}"
            output="${project.build.directory}/container.log"
            append="true"
            log="${project.build.directory}/cargo.log"
            action="start"
            wait="false">
         <configuration type="existing" home="${project.build.directory}/jboss4x">
          <property name="cargo.servlet.port" value="8982"/>
         </configuration>
        </cargo>
       </tasks>
      </configuration>
     </execution>
    </executions>
   </plugin>
   <plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven2-plugin</artifactId>
    <configuration>
     <wait>false</wait>
     <container>
      <containerId>jboss4x</containerId>
      <home>${jboss4x.home}</home>
      <output>${project.build.directory}/container.log</output>
      <append>true</append>
      <log>${project.build.directory}/cargo.log</log>
     </container>
     <configuration>
      <type>existing</type>
      <home>${project.build.directory}/jboss4x</home>
      <properties>
       <cargo.logging>high</cargo.logging>
      </properties>
     </configuration>
    </configuration>
    <executions>
     <execution>
      <id>stop-container</id>
      <phase>post-integration-test</phase>
      <goals>
       <goal>stop</goal>
      </goals>
     </execution>
     <execution>
      <id>create-deployment</id>
      <phase>generate-test-sources</phase>
      <goals>
       <goal>configure</goal>
      </goals>
      <configuration>
       <container>
        <containerId>jboss4x</containerId>
        <home>${jboss4x.home}</home>
        <output>${project.build.directory}/container.log</output>
        <append>true</append>
        <log>${project.build.directory}/cargo.log</log>
       </container>
       <configuration>
        <type>standalone</type>
        <home>${project.build.directory}/jboss4x</home>
        <properties>
         <cargo.jvmargs>
          -Xdebug -Xnoagent
          -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n
         </cargo.jvmargs>
         <cargo.logging>high</cargo.logging>
         <cargo.servlet.port>8982</cargo.servlet.port>
        </properties>
        <deployables>
         <deployable>
          <groupId>your.group.id</groupId>
          <artifactId>your-ear</artifactId>
          <type>ear</type>
         </deployable>
        </deployables>
       </configuration>
      </configuration>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>
</project>

Monday, February 26, 2007

DBUnit and RDMS with special types

If you are using DBUnit for testing your data access layer, and your scheme uses some unusual data types, you need to use data type factories but it won't work if you are about to use at the same time FlatXmlDataSet.
You are going to get errors like:
WARNING - table_name.column_name data type (1111, √ębit√≠) not recognized and will be ignored. See FAQ for more information.
Here is solution that I haven't found on google:
Override default implementation of protected IDatabaseTester newDatabaseTester() throws Exception from DBTestCase to something like this:

protected IDatabaseTester newDatabaseTester() throws Exception {
return new PropertiesBasedJdbcDatabaseTester() {
public IDatabaseConnection getConnection() throws Exception {
IDatabaseConnection databaseConnection = super.getConnection();
DatabaseConfig databaseConfig = databaseConnection.getConfig();
databaseConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());
return databaseConnection;
}
};
}



Where you should use suitable for your database DataTypeFactory.