framework - ¿Cómo ejecutar ScalaTest con Guice DI y Slick?
play framework evolutions (2)
No sé cómo configurar GuiceApplicationBuilder
de tal manera que pueda cargar controladores que requieran que se instale un DatabaseConfigProvider
.
Me gustaría especificar una base de datos postgres alternativa para la prueba, o una base de datos en memoria (si es posible).
Código
class User
extends MySpecs
with OneAppPerTest
{
override def newAppForTest( testData: TestData ) = new GuiceApplicationBuilder()
// Somehow bind a database here, I guess?
.build()
"A test" should "test" in
{
val result = Application.instanceCache[api.controller.User]
.apply( app )
.list()( FakeRequest() )
...
}
}
Stacktrace
[info] - should return an entity *** FAILED ***
[info] com.google.inject.ConfigurationException: Guice configuration errors:
[info]
[info] 1) No implementation for play.api.db.slick.DatabaseConfigProvider was bound.
[info] while locating play.api.db.slick.DatabaseConfigProvider
[info] for parameter 1 at api.controller.User.<init>(User.scala:22)
[info] while locating api.controller.User
[info]
[info] 1 error
[info] at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1042)
[info] at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1001)
[info] at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:321)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:316)
[info] at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234)
[info] at play.api.Application$$anonfun$instanceCache$1.apply(Application.scala:234)
[info] at play.utils.InlineCache.fresh(InlineCache.scala:69)
[info] at play.utils.InlineCache.apply(InlineCache.scala:55)
[info] ...
Hay un poco de configuración en este enfoque, pero el resultado final es justo. En primer lugar, comience con la implementación de su propio GuiceApplicationLoader
extendiéndolo. Vea mi respuesta como implementarlo . ¿Por qué tu propio cargador de aplicaciones? Puede especificar diferentes configuraciones / módulos por modo Prod/Dev/Test
, así como diferentes fuentes de datos. Tu application.conf
principal.conf no tendría configurado el origen de datos. En su lugar, lo movería a configuraciones específicas del entorno que de todos modos se fusionarían con la configuración principal mediante el cargador de aplicaciones. Tu dev.conf
se vería como sigue:
slick.dbs {
default {
driver = "slick.driver.PostgresDriver$",
db {
driver = "org.postgresql.Driver",
url = "jdbc:postgresql://localhost:5432/dev",
user = "postgres"
password = "postgres"
}
}
}
Y el truco ahora es utilizar el mismo nombre de origen de datos, en este caso default
, para todas las demás configuraciones (la base de datos url, los controladores, las credenciales, etc. serían diferentes). Con dicha configuración, sus evolutions
se aplicarán a su base de datos de prueba y desarrollo. Su test.conf
podría verse como sigue:
slick.dbs {
default {
// in memory configuration
}
}
En sus pruebas, use WithApplicationLoader
con su cargador de aplicaciones personalizado y eso es todo.
@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification {
"Application" should {
"return text/html ok for home" in new WithApplicationLoader(new CustomApplicationLoader) {
val home = route(FakeRequest(routes.ApplicationController.home())).get
status(home) must equalTo(OK)
contentType(home) must beSome.which(_ == "text/html")
}
}
}
Dentro de la prueba en sí, tiene acceso a la app: Application
Valor de la app: Application
:
val service = app.injector.instanceOf(classOf[IService])
GuiceApplicationBuilder()
agregar una configuración a su GuiceApplicationBuilder()
, entonces todo debe ser manejado automáticamente por Play Framework. Algo como esto debería ayudar:
val app = new GuiceApplicationBuilder()
.configure(
Configuration.from(
Map(
"slick.dbs.YOURDBNAME.driver" -> "slick.driver.H2Driver$",
"slick.dbs.YOURDBNAME.db.driver" -> "org.h2.Driver",
"slick.dbs.YOURDBNAME.db.url" -> "jdbc:h2:mem:",
"slick.dbs.default.driver" -> "slick.driver.MySQLDriver$",
"slick.dbs.default.db.driver" -> "com.mysql.jdbc.Driver"
)
)
)
.in(Mode.Test)
.build()