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
42.487982
-8.857673