Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce testing overhead when DAO contains action

For accessing objects, a Slick DAO which contains functions returning actions and objects of a stored type were created. Example:

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)
}

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

What is a solid approach to test both functions and minimizing redundancy of code?

I naive method could of course be to test them both with their individual test setups (above is a simple example; there could be a lot of test setup needed to satisfy DB restrictions).

like image 789
Th 00 mÄ s Avatar asked Aug 02 '17 14:08

Th 00 mÄ s


1 Answers

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

Not really. Your findByKeys method does not call findByUserIdAction, so I'm adjusting for that minor detail in this answer.


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

The above code returns a DBIOAction. As the documentation states:

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.

As far as a user of Slick is concerned, there is no meaningful test for a DBIOAction, because by itself it does nothing; it's only a recipe for what one wants to do. To execute the above DBIOAction, you have to materialize it, which is what the following does:

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

The materialized result is what you want to test. One way to do so is to use ScalaTest's ScalaFutures trait. For example, in a spec that mixes in that trait, you could have something like:

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

Take a look at this Slick 3.2.0 test project for more examples: specifically, TestSpec and QueryCoffeesTest.

In summary, don't bother trying to test a DBIOAction in isolation; just test its materialized result.

like image 137
Jeffrey Chung Avatar answered Oct 19 '22 02:10

Jeffrey Chung