Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Test tag
- case object DockerDatabaseTest extends Tag("DockerDatabase")
- //Test harness
- package utilities.database
- import com.dimafeng.testcontainers.{ForAllTestContainer, PostgreSQLContainer}
- import org.scalatest.mockito.MockitoSugar
- import org.scalatest.{Assertion, Suite}
- import org.scalatestplus.play.AppProvider
- import play.api.db.evolutions.Evolutions
- import play.api.db.{Database, Databases}
- import scala.concurrent.{ExecutionContext, Future}
- import scala.util.control.NonFatal
- //Since 'ForAllTestContainer' is used, database evolutions downs must completely clean database
- //otherwise test data will carry over between tests in a suite. 'ForEachTestContrainer' could be used,
- //but connections in pool get corrupted and cannot be used after first test in suite runs.
- //Consider fixing this issue, maybe by pool recreation between tests, and then change to 'ForEachTestContrainer'.
- trait PlayPostgreSQLTest extends Suite with AppProvider with ForAllTestContainer with MockitoSugar {
- override val container: PostgreSQLContainer
- def applyEvolutions(): Unit = {
- withDatabase { database =>
- Evolutions.applyEvolutions(database, autocommit = false)
- }
- }
- def unapplyEvolutions(): Unit = {
- withDatabase { database =>
- Evolutions.cleanupEvolutions(database, autocommit = false)
- }
- }
- def withEvolutions(assertionFun: () => Assertion): Assertion = {
- applyEvolutions()
- val assertion = assertionFun.apply()
- unapplyEvolutions()
- assertion
- }
- def withEvolutions(futureAssertionFun: () => Future[Assertion])(implicit ec: ExecutionContext): Future[Assertion] = {
- applyEvolutions()
- futureAssertionFun
- .apply()
- .map {
- assertion =>
- unapplyEvolutions()
- assertion
- }
- }
- private def withDatabase(block: (Database) => Unit) = {
- val database = Databases(
- driver = "org.postgresql.Driver",
- url = container.jdbcUrl,
- name = "default",
- config = Map(
- "username" -> container.username,
- "password" -> container.password
- )
- )
- try {
- val result = block(database)
- database.shutdown()
- result
- } catch {
- case NonFatal(e) =>
- database.shutdown()
- throw e
- }
- }
- }
- //Mock Play application
- package utilities
- import com.dimafeng.testcontainers.PostgreSQLContainer
- import com.google.inject.AbstractModule
- import com.mohiva.play.silhouette.api.{Silhouette, SilhouetteProvider}
- import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
- import com.mohiva.play.silhouette.api.util.PasswordHasherRegistry
- import modules.authentication.DefaultEnv
- import modules.system.startup.StartUp
- import net.codingwell.scalaguice.ScalaModule
- import org.scalatest.mockito.MockitoSugar
- import play.api.{Application, Configuration, Mode}
- import play.api.inject.bind
- import play.api.inject.guice.GuiceApplicationBuilder
- object TestApplications extends MockitoSugar {
- def basicDatabaseTestApplication(container: PostgreSQLContainer): Application = {
- class FakeSilhouetteModule extends AbstractModule with ScalaModule {
- override def configure(): Unit = {
- bind[Silhouette[DefaultEnv]].toInstance(mock[SilhouetteProvider[DefaultEnv]])
- bind[AuthInfoRepository].toInstance(mock[AuthInfoRepository])
- bind[PasswordHasherRegistry].toInstance(mock[PasswordHasherRegistry])
- }
- }
- val configuration: Configuration = Configuration.from(
- Map(
- "db.default.driver" -> "org.postgresql.Driver",
- "db.default.url" -> container.jdbcUrl,
- "db.default.username" -> container.username,
- "db.default.password" -> container.password,
- "test.dataSourceClass" -> "org.postgresql.ds.PGSimpleDataSource",
- "test.numThreads" -> "10",
- "test.queueSize" -> "1000",
- "test.properties.url" -> container.jdbcUrl,
- "test.properties.user" -> container.username,
- "test.properties.password" -> container.password
- )
- )
- GuiceApplicationBuilder(configuration = configuration)
- .overrides(new FakeSilhouetteModule)
- .overrides(bind[StartUp].toInstance(mock[StartUp]))
- .in(Mode.Test)
- .build()
- }
- }
- // Test Suite
- package test
- import com.dimafeng.testcontainers.PostgreSQLContainer
- import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures}
- import org.scalatest.mockito.MockitoSugar
- import org.scalatest.{BeforeAndAfterEach, TestData}
- import org.scalatestplus.play.PlaySpec
- import org.scalatestplus.play.guice.GuiceOneAppPerTest
- import play.api.Application
- import utilities.TestApplications._
- import utilities.database.PlayPostgreSQLTest
- import utilities.tag.DockerDatabaseTest
- import scala.concurrent.{ExecutionContext, Future}
- class SomeImplementationSpec extends PlaySpec with GuiceOneAppPerTest with ScalaFutures with IntegrationPatience with PlayPostgreSQLTest with MockitoSugar with BeforeAndAfterEach {
- override val container: PostgreSQLContainer = PostgreSQLContainer("postgres:10.5-alpine")
- override def newAppForTest(testData: TestData): Application = {
- basicDatabaseTestApplication(container)
- }
- "An implementation" when {
- "it has to do stuff" should {
- "should do it well" taggedAs DockerDatabaseTest in {
- implicit lazy val executionContext = app.injector.instanceOf[ExecutionContext]
- withEvolutions { () =>
- // Test assertion goes here
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement