How to test methods based on Salat with ScalaTest

I'm writing a web-app using Play 2, Salat (for mongoDB bindin). I would like to test some methods, in the Lesson Model (for instance test the fact that I retrieve the right lesson by id). The problem is that I don't want to pollute my current DB with dummy lessons. How can I use a fake DB using Salat and Scala Test ? Here is one of my test file. It creates two lessons, and insert it into the DB, and it runs some tests on it.

LessonSpec extends FlatSpec with ShouldMatchers {
  object FakeApp extends FakeApplication()

  val newLesson1 = Lesson(
    title = "lesson1",
    level = 5,
    explanations = "expl1",
    questions = Seq.empty)
  LessonDAO.insert(newLesson1)

  val newLesson2 = Lesson(
    title = "lesson2",
    level = 5,
    explanations = "expl2",
    questions = Seq.empty)
  LessonDAO.insert(newLesson2)

  "Lesson Model" should "be retrieved by level" in {
    running(FakeApp) {
      assert(Lesson.findByLevel(5).size === 2)
    }
  }
  it should "be of size 0 if no lesson of the level is found" in {
    running(FakeApp) {
      Lesson.findByLevel(4) should be(Nil)
    }
  }

  it should "be retrieved by title" in {
    running(FakeApp) {
      Lesson.findOneByTitle("lesson1") should be(Some(Lesson("lesson1", 5, "expl1", List())))
    }
  }

}

I searched on the web but i can't find a good link or project that use Salat and ScalaTest.


In my applications, I use a parameter in application.conf to specify the Mongo database name. When initializing my FakeApplication, I override that parameter so that my unit tests can use a real Mongo instance but do not see any of my production data.

Glossing over a few details specific to my application, my tests look something like this:

// wipe any existing data
db.collectionNames.foreach { colName =>
  if (colName != "system.indexes") db.getCollection(colName).drop
}

app = FakeApplication(additionalConfiguration = Map("mongo.db.name" -> "unit-test"))

Salat developer here. My recommendation would be to have a separate test only database. You can populate it with test data to put your test database in a known state - see the casbah tests for how to do this - and then test against it however you like, clearing out collections as necessary.

I use specs2, not scalatest, but the principle is the same - see the source code for the Salat tests.

Here's a good test to get you started: https://github.com/novus/salat/blob/master/salat-core/src/test/scala/com/novus/salat/test/dao/SalatDAOSpec.scala

Note that in my base spec I clear out my test database - this gets run before each spec:

trait SalatSpec extends Specification with Logging {

  override def is =
    Step {
      //      log.info("beforeSpec: registering BSON conversion helpers")
      com.mongodb.casbah.commons.conversions.scala.RegisterConversionHelpers()
      com.mongodb.casbah.commons.conversions.scala.RegisterJodaTimeConversionHelpers()

    } ^
      super.is ^
      Step {
        //        log.info("afterSpec: dropping test MongoDB '%s'".format(SalatSpecDb))
        MongoConnection().dropDatabase(SalatSpecDb)
      }

And then in SalatDAOSpec, I run my tests inside scopes which create, populate and/or clear out individual collections so that the tests can run in an expected state. One hitch: if you run your tests concurrently on the same collection, they may fail due to unexpected state. The solution is either to run your tests in isolated special purpose collections, or to force your tests to run in series so that operations on a single collection don't step on each other as different test cases modify the collection.

If you post to the Scalatest mailing list (http://groups.google.com/group/scalatest-users), I'm sure someone can recommend the correct way to set this up.

链接地址: http://www.djcxy.com/p/11258.html

上一篇: 这是什么样的压缩算法?

下一篇: 如何基于Salat和ScalaTest测试方法