Day to Day Java Java and related Topics

28Oct/100

Did the in-memory database integration testing work as expected?

On my previous post about integration testing with an in-memory database without hibernate I was in the process of finding out which frameworks to use and which in-memory databases to use.

We are now using h2database with Unitils and generated sql schemas for integration testing. H2Database was chosen because it supported most of the syntax and functions/procedures we have in our Firebird database.

The major challenges with this approach is maintainability with the sql schema. I haven't found a good solution for this yet, so we have to update the test schema every time there are changes in the database schema.

Further I will show you a short summary of the setup:


Add some maven dependencies

        <dependency>
            <groupId>org.unitils</groupId>
            <artifactId>unitils-dbunit</artifactId>
            <version>3.1</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.unitils</groupId>
            <artifactId>unitils-orm</artifactId>
            <version>3.1</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.unitils</groupId>
            <artifactId>unitils-dbmaintainer</artifactId>
            <version>3.1</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.2.132</version>
        </dependency>

Unitils needs a property file to figure out the database connection parameters and paths. Stuff it in your resources folder and call it unitils.properties

unitils.modules=database, dbunit, easymock, spring
 
database.driverClassName=org.h2.Driver
database.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
database.dialect=h2
database.userName=sa
database.password=
database.schemaNames=public
database.storedIndentifierCase.h2=auto
database.identifierQuoteString.h2=auto
org.unitils.core.dbsupport.DbSupport.implClassName.h2=com.testing.common.database.H2DbSupport
org.dbunit.dataset.datatype.IDataTypeFactory.implClassName=org.dbunit.ext.h2.H2DataTypeFactory
 
updateDataBaseSchema.enabled=true
 
org.unitils.dbmaintainer.script.ScriptSource.implClassName = com.testing.testutils.ClasspathScriptSource
dbMaintainer.script.locations=classpath:/dbscripts
 
dbMaintainer.autoCreateExecutedScriptsTable=true
dbMaintainer.fromScratchEnabled=false
dbMaintainer.keepRetryingAfterError.enabled = true
dbMaintainer.cleanDb.enabled = false
dbMaintainer.script.fileExtensions=sql
dbMaintainer.generateDataSetStructure.enabled=true
dbMaintainer.updateSequences.enabled=true
 
dataSetStructureGenerator.xsd.dirName=target/xsd

As you may have noticed in the above property file, there are two java implementations. One is to get support for h2database and the other is for getting the paths for the schemas from classpath.

We need to fill the h2database with some tables. Infact i wanted the same schema as i production. I managed to export the firebird database schema and hack away some none working syntax.

The path to the data is defined in unitils.properties: dbMaintainer.script.locations=classpath:/dbscripts
In this path you have to put all your .sql schema files which typically contains a set of create table, insert into statements.

Last but not least, the java test implementation. First the example.

@RunWith(UnitilsJUnit4TestClassRunner.class)
@SpringApplicationContext(value = {"/testContext-service-integrationtests.xml"})
@DataSet(value = {"CommonTestData.xml", "SubscriptionServiceImplIntTest.xml"})
public class EmailServiceImplIntTest {
    @SpringBean("subscriptionService")
    private SubscriptionService subscriptionService;
 
    @Test
    @ExpectedDataSet(value = "SubscriptionServiceImplIntTest.xml")
    public void testGetSubscriptionByCustomerId() throws Exception {
        List<Subscription> subscriptions = subscriptionService.getSubscriptionByCustomerId(152);
        assertTrue(subscriptions.size() > 0);
    }
}

A little explanation to the code above. The test class is annotated with a runner for Unitils, a spring context as I am running spring for my beans and a DataSet annotation. The DataSet annotation defines the test data for your test. I'll give you an example below. I also use unitils annotation for injecting my service.

<?xml version='1.0' encoding='UTF-8'?>
<dataset>
    <subscription id="1" customerId="152" addressId="1" product="Test product"/>
</dataset>

I could go into detail about this, but I am not super happy with the solution. It works, but it lacks a bit automation. How can I update the database schema automatically? Has anyone solved this need for integration tests another way? (not you guys fortunate enough using hibernate)

Related posts:

  1. Integration testing with an in-memory database without hibernate
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment

(required)

No trackbacks yet.