Lift testing with dbunit and specs

Here’s a post about Lift and testing,
using scala specs and dbunit.

We can use dbunit to populate a sample database for testing purposes,
in this example we are going to use the embedded h2 database.

  • 1. Create a sample liftweb (1.1-M8) application using maven 2.2

    
    mvn org.apache.maven.plugins:maven-archetype-plugin:2.0-alpha-4:generate        \
        -DarchetypeGroupId=net.liftweb        \
        -DarchetypeArtifactId=lift-archetype-blank        \
        -DarchetypeVersion=1.1-M8        \
        -DremoteRepositories=http://scala-tools.org/repo-releases        \
        -DgroupId=com.sample -DartifactId=hello
    
    

    And add the testing dependencies to pom.xml (specs, h2database and dbunit)

    
    
    <dependency>
        <groupId>org.scala-tools.testing</groupId>
        <artifactId>specs</artifactId>
        <version>1.4.4</version>                  
        <scope>test</scope>
    </dependency>                                 
    
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.2.125</version>   
        <scope>test</scope>     
    </dependency>                     
    
    <dependency>
        <groupId>org.dbunit</groupId>
        <artifactId>dbunit</artifactId>
        <version>2.4.7</version>
        <scope>test</scope>
    </dependency>
    
    
  • 2. Create a sample model vo (Item with name and id)

    in src/main/scala/com/sample/model/Item.scala,
    a sample object with a string attribute name that cannot be empty.

    
    package com.sample.model
    
    import net.liftweb.mapper.{By, IdPK,
                               LongKeyedMapper, LongKeyedMetaMapper,
                               MappedString}
    
    class Item extends LongKeyedMapper[Item] with IdPK {
        def getSingleton = Item
    
        object name extends MappedString(this, 100) {
            override def validations = valMinLen(1, "Must be not empty") _ ::
                                       super.validations
        }
    }
    
    object Item extends Item with LongKeyedMetaMapper[Item] {
        def findByName(name: String): List[Item] = {
            Item.findAll(By(Item.name, name))
        }
    }
    
    

    We can test the compilation to let maven download the dependencies
    without testing : mvn package -Dmaven.test.skip=true

  • 3. Create a sample Specs test file for item

    in src/test/scala/com/sample/model/ItemSpecs.scala,

    
    package com.sample.model
    
    import org.specs.Specification
    import org.specs.runner.JUnit4
    
    class ItemSpecsAsTest extends JUnit4(ItemSpecs)
    
    object ItemSpecs extends Specification {
        "Item" should {                     
            "do nothing wrong" in {
                true must beTrue
            }
        }
    }
    
    
  • 4. Create a database util class to initialize database and populate data

    in src/test/scala/com/sample/utils/DBUtil.scala,

    it will initialize the default database connection identifier using the properties file in
    src/test/resources (by default src/test/resources/props/test.default.props)

    and will let us choose a dbunit dataset file to populate the test data using
    DBUtil.setupDB(“dbunit_database_file.xml”)

    
    package com.sample.utils                                                     
    
    import net.liftweb.mapper.{DB,
                              ConnectionIdentifier, DefaultConnectionIdentifier,
                              StandardDBVendor}                                 
    import net.liftweb.util.{Log, Props}                                        
    
    import org.dbunit.dataset.{IDataSet}
    import org.dbunit.dataset.xml.{XmlDataSet}
    import org.dbunit.database.{DatabaseConfig, DatabaseConnection}
    import org.dbunit.operation.{DatabaseOperation}                
    
    object DBUtil {
        private var dataset: IDataSet      = null
        private var dbunitConnection: DatabaseConnection = null
    
        lazy val connectionIdentifier: () => ConnectionIdentifier = {
            () => DefaultConnectionIdentifier                        
        }                                                            
    
        def initialize = {
            DB.defineConnectionManager(connectionIdentifier(),
                                      new StandardDBVendor(Props.get("db.driver").openOr(""),
                                                           Props.get("db.url").openOr(""),   
                                                           Props.get("db.user"),             
                                                           Props.get("db.password")))        
        }                                                                                    
    
        def setupDB(filename: String) = {
            this.dataset = new XmlDataSet(this.getClass().getClassLoader().getResourceAsStream(filename))
    
            DB.use(connectionIdentifier()) {
                conn => {
                    this.dbunitConnection = new DatabaseConnection(conn)
                    DatabaseOperation.CLEAN_INSERT.execute(this.dbunitConnection, this.dataset)
                }
            }
        }
    
        def shutdownDB = {
            DB.use(connectionIdentifier()) {
                conn => {
                    try {
                        DatabaseOperation.DELETE.execute(this.dbunitConnection, this.dataset)
                    }
                    catch {
                        case e: Exception => Log.error(e.getMessage)
                    }
                }
            }
    
        }
    }
    
    
  • 5. Now we can do some more interesting test

    using a sample dataset in src/test/resources/dbunit/item_test.xml,
    the lift Shemifier class will create the database table on the beggining of the test
    and destroy it at the end.

    
    package com.sample.model                                                        
    
    import net.liftweb.mapper.{Schemifier}
    import net.liftweb.util.{Log}         
    
    import com.sample.utils.DBUtil
    
    import org.specs.Specification
    import org.specs.runner.JUnit4
    
    class ItemSpecsAsTest extends JUnit4(ItemSpecs)
    
    object ItemSpecs extends Specification {
        "Item" should {                     
            doFirst {                       
                DBUtil.initialize           
                Schemifier.schemify(true, Log.infoF _ , Item)
                DBUtil.setupDB("dbunit/item_test.xml")       
            }                                                
    
            "save without problem" in {
                val item = new Item
                item.name("item name")
    
                item.save must beTrue
                (Item.findAll.length == 3) must beTrue
            }
    
            "find by name" in {
                val items = Item.findByName("Item 1")
                items.length must_== 1
            }
    
            "delete without problem" in {
                val items = Item.findByName("item name")
    
                items.length must_== 1
                items(0).delete_! must beTrue
                Item.findAll.length must_== 2
            }
    
            doLast {
                DBUtil.shutdownDB
                Schemifier.destroyTables_!!(Log.infoF _, Item)
            }
        }
    }
    
    
    

Simple and funny šŸ™‚

The sample code can be found in
http://github.com/jgoday/sample_lift_testing

Advertisements
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: