Search⌘ K
AI Features

Testing the Repository

Explore integration testing techniques for repository implementations in Scala HTTP APIs. Learn to manage database setup, execute tests for loading, saving, and updating products, and apply ScalaCheck for data generation. Understand handling asynchronous operations and database constraints in functional service testing.

Global operations

Now that our parts are in place, we can write an integration test for our repository implementation. First, we need to do some things globally for the test scope.

Scala
private val dbConfig: DatabaseConfig[JdbcProfile] =
DatabaseConfig.forConfig("database", system.settings.config)
private val repo = new Repository(dbConfig)
override protected def beforeEach(): Unit = {
flyway.clean()
val _ = flyway.migrate()
super.beforeEach()
}
override protected def afterEach(): Unit = {
flyway.clean()
super.afterEach()
}
override protected def afterAll(): Unit = {
repo.close()
super.afterAll()
}

Here, we clean our database, run the migration, and after we have executed all the tests, close the repository.

Remember: not cleaning the database between tests might be an even more thorough test.

loadProduct

Let’s move on to the test for loading a single product.

Scala
"#loadProduct" when {
"the ID does not exist" must {
"return an empty list of rows" in {
val id = UUID.randomUUID
for {
rows <- repo.loadProduct(id)
} yield {
rows must be(empty)
}
}
}
"the ID exists" must {
"return a list with all product rows" in {
genProduct.sample match {
case None => fail("Could not generate data sample!")
case Some(p) =>
for {
_ <- repo.saveProduct(p)
rows <- repo.loadProduct(p.id)
} yield {
Product.fromDatabase(rows) match {
case None => fail("No product created from database rows!")
case Some(c) =>
c.id must be(p.id)
c mustEqual p
}
}
}
}
}
}

We create one Repository instance for all our tests here. The downside is that if one test ...