简体   繁体   中英

Test CRUD function in Playframework unit tests using ScalaTest

I created some CRUD functions with scala and I want to test them using unit test. For example I want to test the send method:

class MyFunctionDAO @Inject() (db: DB) {

  def collection: JSONCollection = db.collection[JSONCollection]("myCollection")

  def save(myObject: MyObject): Future[Either[String, UUID]] = {
    collection.insert(myObject).map {
      case result if result.ok == true => Right(myObject._id)
      case result => Left(result.message)
    }
  }
}

How can I proceed? Any example please?

You can use ScalaMock to mock your db instance and set expectations and returned values. There is a page in ScalaTest doc about that.

Following example describes approach and may have issues

import org.scalatest.FlatSpec
import org.scalamock.scalatest.MockFactory

class MyFunctionDAOSpec extends FlatSpec with MockFactory {
  val db = mock[DB]
  val col = mock[JSONCollection]
  (col.insert _) expects (myObj) returning (okResult)
  (col.insert _) expects (myObj2) returning (failResult)
  (db.collection _) expects ("myCollection") returning (col) 
  //...

  val dao = new MyFunctionDAO(db)

  "DAO" should "return Right" in {
    dao.save(myObj) should be (Right(myObj._id))
  }

  it should "return Left" in {
    dao.save(myObj2) should be (Left("my error message"))
  }
}

I am relatively new into testing, admittedly, but I'll share my opinion as it's being forged. It is my perception that CRUD operations should not be unit-tested. They should be integration tested instead. Because when we unit-test the API method, we are trying to test that it abides its contract. But what exactly does it mean that "this method should add this entity with those properties to the DB"? Say, the method contains some logic that parses the incoming DTO and converts it to DB entities/relations/etc.; but we ought not test for some expected result of conversion, because it's "how" the method works, not "what" it does: it's a test of implementation, not contract; even more, this whole logic is only needed because we use that DB model, and not some other model, and it has nothing to do with CRUD operation itself.

However we probably should not leave conversion logics untested, especially if it's not quite trivial. So, we could test it directly: instead of testing write(x)=f(convert(x)) for actually trying to write x, with convert(x) being private part of implementation (thus skipped from tests), we can skip unit-testing f() - leaving that for integration tests - and test directly convert(x).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM