当 DAO 包含操作时减少测试开销

Reduce testing overhead when DAO contains action

为了访问对象,创建了一个 Slick DAO,其中包含返回操作的函数和存储类型的对象。示例:

def findByKeysAction(a: String, b: String, c: String = {
  Users.filter(x => x.a === a && x.b === b && x.c === c).result
}

def findByKeys(a: String, b: String, c: String): Future[Option[foo]] = {
  db.run(findByKeysAction(consumerId, contextId, userId)).map(_.headOption)
}

注意非基于动作的函数如何将另一个函数包装在 db.run() 中。

什么是测试这两个函数和最小化代码冗余的可靠方法?

我天真的方法当然可以是用它们各自的测试设置来测试它们(上面是一个简单的例子;可能需要很多测试设置来满足数据库限制)。

Notice how the non-action-based function wraps the other in db.run().

不是真的。您的 findByKeys 方法不会调用 findByUserIdAction,因此我正在针对此答案中的次要细节进行调整。


def findByUserIdAction(userId: String) = {
  Users.filter(_.userId === userId).result
}

上面的代码returns一个DBIOAction。正如 documentation 所述:

Just like a query, an I/O action is only a description of an operation. Creating or composing actions does not execute anything on a database.

就 Slick 的用户而言,DBIOAction 没有有意义的测试,因为它本身什么都不做;这只是一个人想做什么的秘诀。要执行上面的 DBIOAction,你必须 materialize 它,这就是下面的内容:

def findByUserId(userId: String): Future[Option[User]] = {
  db.run(findByUserIdAction(userId)).map(_.headOption)
}

具体化的结果就是你要测试的。一种方法是使用 ScalaTest 的 ScalaFutures 特征。例如,在混合了该特征的规范中,您可以有类似的内容:

"Users" should "return a single user by id" in {
  findByUserId("id3").futureValue shouldBe Option(User("id3", ...))
}

看看这个Slick 3.2.0 test project for more examples: specifically, TestSpec and QueryCoffeesTest

总而言之,不要试图孤立地测试 DBIOAction;只是测试它的具体化结果。