/spock-dbunit

Dbunit extension for spock avoiding a separate xml file

Primary LanguageGroovy

Build Status Download

spock-dbunit

Dbunit extension for spock avoiding writing separate xml files when doing db related tests.

Normally when using dbUnit, you specify your sql data in a separate xml file. This can become cumbersome and makes it more difficult to understand how your test is set up. You can avoid this using this spock extension.

Using groovy's MarkupBuilder you just specify your sql as a field like in the example below:

     class MyDbUnitTest extends Specification{

        DataSource dataSource

        @DbUnit
        def content =  {
            User(id: 1, name: 'jackdaniels', createdOn: '[NOW]')
        }

        ...

The above code will setup dbUnit to insert the specified row in the User table. It will take the data source specified in the datasource field to get the connection to the database.

Configuration

Finding the DataSource

dbUnit needs a DataSource to connect to the database. There are several ways to do this:

  • by specifying a datasourceProvider as an extra closure parameter in the @DbUnit annotation. The closure returns a configured DataSource
     class MyDbUnitTest extends Specification{
     
         @DbUnit(datasourceProvider = {
             inMemoryDataSource()
         })
         def content =  {
             User(id: 1, name: 'janbols')
         }
     
         ...
  • by specifying a DataSource field in your specification
     class MyDbUnitTest extends Specification{
     
         DataSource dataSource
     
         @DbUnit
         def content = {
             User(id: 1, name: 'janbols')
         }
     
         def setup() {
             dataSource = inMemoryDataSource()
         }    
         ...
  • by specifying a @Shared DataSource field in your specification
     class MyDbUnitTest extends Specification{
    
         @Shared DataSource dataSource
     
         @DbUnit def content =  {
             User(id: 1, name: 'janbols')
         }
     
         def setupSpec(){
             dataSource = inMemoryDataSource()
         }
         ...

Configuring the DatabaseTester

The dbUnit DatabaseTester can also be configured as an extra closure in the @DbUnit annotation. An example can be seen below:

     class MyDbUnitTest extends Specification{

         @DbUnit(configure={IDatabaseTester it ->
            it.setUpOperation = DatabaseOperation.CLEAN_INSERT
            it.tearDownOperation = DatabaseOperation.TRUNCATE_TABLE
    
            (it.dataSet as ReplacementDataSet)
                .addReplacementObject('[TOMORROW]', LocalDateTime.now().plusDays(1).toDate())
         }) 
         def content =  {
            User(id: 1, name: 'jackdaniels', created: '[NOW]', expiration: '[TOMORROW]')
        }
        
        ...

In the example above, the DatabaseTester is being configured to do a clean insert during setup and a table truncate during cleanup. In addition all [TOMORROW] fields are being replaced with the date of tomorrow.

Specifying the schema

You can specify the default schema using the schema field in the DbUnit annotation. The example below shows an example:

     class MyDbUnitTest extends Specification{

        DataSource dataSource
    
        @DbUnit(schema = "otherSchema")
        def content = {
            User(id: 1, name: 'janbols')
        }
        
        ...

Use different content per feature

You can specify different database content per feature. This can be done by adding a DbUnit annotation on the feature method. The content can be specified in the content field of the DbUnit annotation. It accepts a closure that specifies the database content. When there's also a DbUnit annotation on a field containing database content, the one on the feature takes precedence and the one on the field is ignored. An example is shown below:

     class MyDbUnitTest extends Specification{
            
            //default db content for all features that don't override this one
            @DbUnit
            def content =  {
                User(id: 3, name: 'dinatersago')
            }
        
            ...
        
            //DbUnit on a feature overrides the one in the content field
            @DbUnit(content = {
                User(id: 1, name: 'janbols')
            })
            def "feature with own database content"() {
                ...
            }
        
            def "feature without own database content taking the content of the field"() {
                ...
            }
            
            ...

Getting started

To enable this Spock extension, you need to add a dependency to this project and a dependency to dbUnit

using Maven:

Enable the JCenter repository:

<repository>
  <id>jcenter</id>
  <name>JCenter Repo</name>
  <url>http://jcenter.bintray.com</url>
</repository>

Add spock-reports to your :

<dependency>
  <groupId>com.github.janbols</groupId>
  <artifactId>spock-dbunit</artifactId>
  <version>0.4</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.dbunit</groupId>
  <artifactId>dbunit</artifactId>
  <version>2.5.1</version>
  <scope>test</scope>
</dependency>

using Gradle:

repositories {
  jcenter()
}

dependencies {
    testCompile 'com.github.janbols:spock-dbunit:0.4'
    testCompile 'org.dbunit:dbunit:2.5.1'
}

If you prefer, you can just download the jar directly from JCenter.

Changes

Version 0.4

  • Solve a bug that allows you to specify connection configuration properties (#9)
  • Solve a bug when no DbUnit annotation exists on a field but only on features (#10)

Version 0.3

  • Be able to override the DbUnit content per feature (#7)
  • Be able to specify the schema (#6)

Version 0.2

  • Easier way to see if spring-jdbc is on the classpath
  • Publish in bintray

Version 0.1

  • Initial version