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=helloAnd 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
No trackbacks yet.