Advertisement
Guest User

Untitled

a guest
Feb 19th, 2019
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.31 KB | None | 0 0
  1. //Test tag
  2. case object DockerDatabaseTest extends Tag("DockerDatabase")
  3.  
  4. //Test harness
  5. package utilities.database
  6.  
  7. import com.dimafeng.testcontainers.{ForAllTestContainer, PostgreSQLContainer}
  8. import org.scalatest.mockito.MockitoSugar
  9. import org.scalatest.{Assertion, Suite}
  10. import org.scalatestplus.play.AppProvider
  11. import play.api.db.evolutions.Evolutions
  12. import play.api.db.{Database, Databases}
  13.  
  14. import scala.concurrent.{ExecutionContext, Future}
  15. import scala.util.control.NonFatal
  16.  
  17. //Since 'ForAllTestContainer' is used, database evolutions downs must completely clean database
  18. //otherwise test data will carry over between tests in a suite. 'ForEachTestContrainer' could be used,
  19. //but connections in pool get corrupted and cannot be used after first test in suite runs.
  20. //Consider fixing this issue, maybe by pool recreation between tests, and then change to 'ForEachTestContrainer'.
  21. trait PlayPostgreSQLTest extends Suite with AppProvider with ForAllTestContainer with MockitoSugar {
  22.  
  23. override val container: PostgreSQLContainer
  24.  
  25. def applyEvolutions(): Unit = {
  26. withDatabase { database =>
  27. Evolutions.applyEvolutions(database, autocommit = false)
  28. }
  29. }
  30.  
  31. def unapplyEvolutions(): Unit = {
  32. withDatabase { database =>
  33. Evolutions.cleanupEvolutions(database, autocommit = false)
  34. }
  35. }
  36.  
  37. def withEvolutions(assertionFun: () => Assertion): Assertion = {
  38. applyEvolutions()
  39. val assertion = assertionFun.apply()
  40. unapplyEvolutions()
  41. assertion
  42. }
  43.  
  44. def withEvolutions(futureAssertionFun: () => Future[Assertion])(implicit ec: ExecutionContext): Future[Assertion] = {
  45. applyEvolutions()
  46. futureAssertionFun
  47. .apply()
  48. .map {
  49. assertion =>
  50. unapplyEvolutions()
  51. assertion
  52. }
  53. }
  54.  
  55. private def withDatabase(block: (Database) => Unit) = {
  56. val database = Databases(
  57. driver = "org.postgresql.Driver",
  58. url = container.jdbcUrl,
  59. name = "default",
  60. config = Map(
  61. "username" -> container.username,
  62. "password" -> container.password
  63. )
  64. )
  65. try {
  66. val result = block(database)
  67. database.shutdown()
  68. result
  69. } catch {
  70. case NonFatal(e) =>
  71. database.shutdown()
  72. throw e
  73. }
  74. }
  75. }
  76.  
  77. //Mock Play application
  78. package utilities
  79.  
  80. import com.dimafeng.testcontainers.PostgreSQLContainer
  81. import com.google.inject.AbstractModule
  82. import com.mohiva.play.silhouette.api.{Silhouette, SilhouetteProvider}
  83. import com.mohiva.play.silhouette.api.repositories.AuthInfoRepository
  84. import com.mohiva.play.silhouette.api.util.PasswordHasherRegistry
  85. import modules.authentication.DefaultEnv
  86. import modules.system.startup.StartUp
  87. import net.codingwell.scalaguice.ScalaModule
  88. import org.scalatest.mockito.MockitoSugar
  89. import play.api.{Application, Configuration, Mode}
  90. import play.api.inject.bind
  91. import play.api.inject.guice.GuiceApplicationBuilder
  92.  
  93. object TestApplications extends MockitoSugar {
  94.  
  95. def basicDatabaseTestApplication(container: PostgreSQLContainer): Application = {
  96. class FakeSilhouetteModule extends AbstractModule with ScalaModule {
  97. override def configure(): Unit = {
  98. bind[Silhouette[DefaultEnv]].toInstance(mock[SilhouetteProvider[DefaultEnv]])
  99. bind[AuthInfoRepository].toInstance(mock[AuthInfoRepository])
  100. bind[PasswordHasherRegistry].toInstance(mock[PasswordHasherRegistry])
  101. }
  102. }
  103.  
  104. val configuration: Configuration = Configuration.from(
  105. Map(
  106. "db.default.driver" -> "org.postgresql.Driver",
  107. "db.default.url" -> container.jdbcUrl,
  108. "db.default.username" -> container.username,
  109. "db.default.password" -> container.password,
  110. "test.dataSourceClass" -> "org.postgresql.ds.PGSimpleDataSource",
  111. "test.numThreads" -> "10",
  112. "test.queueSize" -> "1000",
  113. "test.properties.url" -> container.jdbcUrl,
  114. "test.properties.user" -> container.username,
  115. "test.properties.password" -> container.password
  116. )
  117. )
  118.  
  119. GuiceApplicationBuilder(configuration = configuration)
  120. .overrides(new FakeSilhouetteModule)
  121. .overrides(bind[StartUp].toInstance(mock[StartUp]))
  122. .in(Mode.Test)
  123. .build()
  124. }
  125. }
  126.  
  127. // Test Suite
  128. package test
  129.  
  130. import com.dimafeng.testcontainers.PostgreSQLContainer
  131. import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures}
  132. import org.scalatest.mockito.MockitoSugar
  133. import org.scalatest.{BeforeAndAfterEach, TestData}
  134. import org.scalatestplus.play.PlaySpec
  135. import org.scalatestplus.play.guice.GuiceOneAppPerTest
  136. import play.api.Application
  137. import utilities.TestApplications._
  138. import utilities.database.PlayPostgreSQLTest
  139. import utilities.tag.DockerDatabaseTest
  140.  
  141. import scala.concurrent.{ExecutionContext, Future}
  142.  
  143. class SomeImplementationSpec extends PlaySpec with GuiceOneAppPerTest with ScalaFutures with IntegrationPatience with PlayPostgreSQLTest with MockitoSugar with BeforeAndAfterEach {
  144.  
  145. override val container: PostgreSQLContainer = PostgreSQLContainer("postgres:10.5-alpine")
  146.  
  147. override def newAppForTest(testData: TestData): Application = {
  148. basicDatabaseTestApplication(container)
  149. }
  150.  
  151. "An implementation" when {
  152. "it has to do stuff" should {
  153. "should do it well" taggedAs DockerDatabaseTest in {
  154. implicit lazy val executionContext = app.injector.instanceOf[ExecutionContext]
  155. withEvolutions { () =>
  156. // Test assertion goes here
  157. }
  158. }
  159. }
  160. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement