Pregunta Probando la aplicación Play + Slick


Tengo una aplicación CRUD simple construida con Scala Play 2.4.3 y Play-slick 1.1.0 (slick 3.1.0) que utiliza una base de datos MySQL para el almacenamiento persistente.

Estaba intentando crear las pruebas para mi aplicación y vi 2 opciones principales:

  • El acceso a la base de datos se burla, que por lo que he visto, requiere algunos cambios de código
  • hacer pruebas usar una base de datos alternativa (probablemente, en la memoria H2).

¿Cuál es el mejor enfoque (ventajas y desventajas)?

Prefiero el segundo enfoque, pero encuentro algunas dificultades para configurar las pruebas.

¿Que necesito hacer? Primero, creo que necesito hacer las pruebas con un FakeApplication, ¿derecho? ¿Necesito alguna dependencia sbt para poder hacer eso?

Después de eso, ¿cómo especifico usar la base de datos H2?


6
2017-11-29 22:10


origen


Respuestas:


Tuve la misma lucha y se me ocurrió una solución como esta (utilizando el segundo enfoque):

Cree un contexto para que DAO utilice:

trait BaseContext{

  def dbName: String

  val dbConfig = DatabaseConfigProvider.get[JdbcProfile](dbName)
  val db = dbConfig.db
  val profile = dbConfig.driver
  val tables = new Tables {  // this is generated by Schema Code Generator
    override val profile: JdbcProfile = dbConfig.driver
  }
}

@Singleton
class AppContext extends BaseContext{
  def dbName = "mysql"  // name in your conf right after "slick.dbs"
}

@Singleton
class TestingContext extends BaseContext{
  def dbName = "h2"
}

Luego cree un módulo para enlazar la inyección, y no olvide habilitarlo en conf usando play.modules.enabled += "your.Module":

class ContextModule(environment: Environment, configuration: Configuration) extends AbstractModule {

  override def configure(): Unit = {
    if (configuration.getString("app.mode").contains("test")) {
      bind(classOf[BaseContext])
          .to(classOf[TestingContext])
    } else {
      bind(classOf[BaseContext])
          .to(classOf[AppContext])
    }
  }
}

E inyectalo en cada DAO que hayas creado:

class SomeDAO @Inject()(context: BaseContext){

  val dbConfig = context.dbConfig
  val db = context.db
  val tables = context.tables
  import tables.profile.api._

  def otherStuff....
  // you can call db.run(...), tables.WhateverYourTableIs, tables.TableRowCaseClass, ...
}

Y el último paso, su archivo de configuración. En mi caso, utilicé app.mode Para marcar el entorno, y lo uso por separado. .conf para diferentes ambientes. De causa, en estos conf debe tener la configuración de base de datos correcta. Aquí está la muestra:

app.mode = "test"

# Database configuration
slick.dbs = {
  # for unit test
  h2 {
    driver = "slick.driver.H2Driver$"
    db = {
      url = "jdbc:h2:mem:test;MODE=MYSQL"
      driver = "org.h2.Driver"
      keepAliveConnection = true
    }
  }
}

Estoy bastante seguro de que mi solución no es elegante, pero entrega los productos. :) Cualquier solución mejor es bienvenida!


6
2017-12-03 02:37



mi solución fue agregar step(Play.start(fakeApp)) al comienzo de cada especificación, y step(Play.stop(fakeApp)) al final de cada especificación

También:

def fakeApp: FakeApplication = {
FakeApplication(additionalConfiguration =
  Map(
    "slick.dbs.default.driver" -> "slick.driver.H2Driver$",
    "slick.dbs.default.db.driver" -> "org.h2.Driver",
    "slick.dbs.default.db.url" -> "jdbc:h2:mem:play"
  ))

}

Esto fue necesario porque estoy usando juego resbaladizo, que requiere configuraciones como:

slick.dbs.default.driver = "slick.driver.MySQLDriver$"
slick.dbs.default.db.driver = "com.mysql.jdbc.Driver"
slick.dbs.default.db.url = "jdbc:mysql://localhost/database"
slick.dbs.default.db.user = "user"
slick.dbs.default.db.password = "password"

más información sobre el documentos


3
2017-12-06 23:41