2015-10-28 16 views
11

Vorrei eseguire manualmente lo script di evoluzione all'inizio di ogni file di test. Sto lavorando con Play! 2.4 e Slick 3.Come applicare manualmente le evoluzioni nei test con Slick e Play! 2.4

Secondo la documentazione, la strada da percorrere sembra essere:

Evolutions.applyEvolutions(database) 

ma non riesco a ottenere un'istanza del mio database. Nel documentationplay.api.db.Databases viene importato al fine di ottenere un'istanza di database, ma se cerco di importarlo, ottengo questo errore: object Databases is not a member of package play.api.db

Come posso ottenere un'istanza di mio database per eseguire lo script evoluzione?

Edit: come richiesto nei commenti, qui è l'intero codice sorgente che dà l'errore:

import models._ 
import org.scalatest.concurrent.ScalaFutures._ 
import org.scalatest.time.{Seconds, Span} 
import org.scalatestplus.play._ 
import play.api.db.evolutions.Evolutions 
import play.api.db.Databases 

class TestAddressModel extends PlaySpec with OneAppPerSuite { 
    lazy val appBuilder = new GuiceApplicationBuilder() 
    lazy val injector = appBuilder.injector() 
    lazy val dbConfProvider = injector.instanceOf[DatabaseConfigProvider] 

    def beforeAll() = { 
    //val database: Database = ??? 
    //Evolutions.applyEvolutions(database) 
    } 

    "test" must { 
    "test" in { } 
    } 
} 
+0

puoi pubblicare il codice sorgente che sta causando la errore? – kukido

+0

Qui viene posta la stessa domanda: http://stackoverflow.com/questions/31884182/play-2-4-2-play-slick-1-0-0-how-do-i-apply-database-evolutions- to-a-slick-man – Simon

+0

Ho avuto problemi con la risposta di seguito che sembrava funzionare inizialmente, e ho trovato una soluzione diversa che faccio riferimento qui invece di copiare: http://stackoverflow.com/questions/42368523/play-tests/42416309 # 42.416.309 connessioni -con-Database-troppo-molti-. Le evoluzioni – JulienD

risposta

11

finalmente ho trovato questa soluzione. I iniettare con Guice:

lazy val appBuilder = new GuiceApplicationBuilder() 

lazy val injector = appBuilder.injector() 

lazy val databaseApi = injector.instanceOf[DBApi] //here is the important line 

(dovete importare play.api.db.DBApi.)

E nel mio test, faccio semplicemente il seguente (in realtà ho utilizzare un altro database per i miei test):

override def beforeAll() = { 
    Evolutions.applyEvolutions(databaseApi.database("default")) 
} 

override def afterAll() = { 
    Evolutions.cleanupEvolutions(databaseApi.database("default")) 
} 
+0

Usando questa tecnica, dopo aver scritto più test ottengo un errore "Troppe connessioni": http://stackoverflow.com/questions/42368523/play-tests-with-database-too-many-connections?noredirect=1#comment71900106_42368523. Qualche idea su dove si trova la perdita? – JulienD

2

Considerando che si sta utilizzando Gioca 2.4, in cui evoluzioni sono stati spostati in un modulo separato, avete aggiungere evolutions alle dipendenze del progetto.

libraryDependencies += evolutions 
+0

sono già state aggiunte nel file build.sbt – Simon

0

Trovo il modo più semplice per eseguire i test con evoluzioni applicate è quello di utilizzare FakeApplication, e l'ingresso le informazioni di connessione per il DB manualmente .

def withDB[T](code: => T): T = 
    // Create application to run database evolutions 
    running(FakeApplication(additionalConfiguration = Map(
    "db.default.driver" -> "<my-driver-class>", 
    "db.default.url"  -> "<my-db-url>", 
    "db.default.user"  -> "<my-db>", 
    "db.default.password" -> "<my-password>", 
    "evolutionplugin"  -> "enabled" 
    ))) { 
    // Start a db session 
    withSession(code) 
    } 

usare in questo modo:

"test" in withDB { } 

Ciò consente, ad esempio, di utilizzare un database in memoria per accelerare il test di unità.

È possibile accedere all'istanza DB come play.api.db.DB se necessario. Avrai anche bisogno di import play.api.Play.current.

+0

So come abilitare autoEvolution, quello che voglio fare è eseguire lo script evolution per ogni file di test anche se non ci sono state modifiche (nel file 1.sql). Ecco perché voglio avere un'istanza di database e non vedo dove posso averlo con il tuo codice. Inoltre, ho già impostato diverse configurazioni per il mio test con GuiceApplicationBuilder. – Simon

+0

Perché non inizi con un DB vuoto per ogni test e applichi tutte le evoluzioni? In caso contrario, si avranno problemi se i test non riportano il DB esattamente allo stato giusto. – jazmit

+0

Questo è esattamente quello che voglio fare! ;) (Non con un database in memoria ma non penso che sarebbe diverso.) – Simon

0

Utilizzare FakeApplication per leggere la configurazione del DB e fornire un'istanza DB.

def withDB[T](code: => T): T = 
    // Create application to run database evolutions 
    running(FakeApplication(additionalConfiguration = Map(
     "evolutionplugin" -> "disabled"))) { 
    import play.api.Play.current 
    val database = play.api.db.DB 
    Evolutions.applyEvolutions(database) 
    withSession(code) 
    Evolutions.cleanupEvolutions(database) 
    } 

usare in questo modo:

"test" in withDB { } 
+2

Il problema con il tuo codice è che poiché utilizzo Slick posso ottenere un'istanza del mio database con play.api.db.DB – Simon

1

di avere accesso a play.api.db.Databases, è necessario aggiungere JDBC per le dipendenze:

libraryDependencies += jdbc 

Spero che aiuti alcune persone che passano qui.

EDIT: il codice sarebbe quindi simile a questa:

import play.api.db.Databases 

val database = Databases(
    driver = "com.mysql.jdbc.Driver", 
    url = "jdbc:mysql://localhost/test", 
    name = "mydatabase", 
    config = Map(
    "user" -> "test", 
    "password" -> "secret" 
) 
) 

È ora hanno un'istanza del DB, e può eseguire query su di esso:

val statement = database.getConnection().createStatement() 
val resultSet = statement.executeQuery("some_sql_query") 

Si può vedere di più dal docs

EDIT: errore di battitura

+0

Grazie, ma non è la domanda ... – Simon

+0

La mia risposta non è stata completa abbastanza credo. Quando hai questo 'play.api.db.Database', puoi creare il tuo oggetto Database come nei documenti, e lì hai la tua istanza di database, su cui puoi usare' Evolutions.applyEvolutions (database) ' –

+0

Come può avete l'istanza del database in modo diverso rispetto a come la ottengo nella risposta che ho fornito? – Simon