2017-02-21 42 views
6

Чтобы иметь базу данных, доступные в scalatest с эволюциями я использую это расширение по умолчанию PlaySpec вдохновленного this SO question:Play тестов с базой данных: «Слишком много соединений»

trait ResetDbSpec extends PlaySpec with BeforeAndAfterAll { 
    lazy val appBuilder = new GuiceApplicationBuilder() 
    lazy val injector = appBuilder.injector() 
    lazy val databaseApi = injector.instanceOf[DBApi] 

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

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

Это относится эволюции к базе данных при запуске свита, и возвращает их, когда пакет заканчивается. Тест затем выглядит

class ProjectsSpec extends ResetDbSpec with OneAppPerSuite { ... 

После добавления дополнительных испытаний, как это, я попал момент, когда некоторые тесты, которые добились успеха, когда я запускаю их в покое, потерпеть неудачу с этой ошибкой:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"

Как можно увидеть в приведенном выше коде, я попытался добавить строку

databaseApi.database("default").shutdown() 

в afterAll(), чтобы смягчить, но это не имело никакого эффекта. Я попытался не запускать тесты параллельно, но и никакого эффекта. Где я могу открыть db-соединения, не закрывая их, и где я должен позвонить shutdown()?

N.B. Я использую Play 2.5.10 и Slick 3.1.

+0

Является ли приложение попыткой сохранить больше соединений в пуле, чем база данных позволит открыть? –

+0

@MichaelZajac Как я могу проверить это? – JulienD

+0

Помогает ли изменение 'lazy val databaseApi'' def databaseApi'? В противном случае вы можете проверить https://www.playframework.com/documentation/2.5.x/SettingsJDBC, чтобы настроить максимальный размер пула. Кроме того, как сказал @MichaelZajac, вы можете проверить свою локальную конфигурацию базы данных, чтобы узнать, сколько подключений она позволяет. – Eric

ответ

1

У меня есть много тестов (около 500), и я не получаю эту ошибку, с той лишь разницей, я с вашего кода, что я добавить

databaseApi.database("default").getConnection().close() 

и

Play.stop(fakeApplication) 

для интеграционных тестов.

Сообщите мне, если это что-то изменит.

+0

К сожалению, это не так :(Как только я вызываю 'databaseApi' либо в BeforeAll, либо AfterAll, я получаю ошибку (т. Е. Вычисляется ленивый val). Возможно, я неправильно понял, я добавил эти две строки, которые вы предлагаете в' afterAll() 'У меня всего ~ 120 тестов.Может быть, MySQL, или гладкий драйвер для этого, для чего-то в этом. – JulienD

+0

Нет, я думаю, что вы хорошо поняли. Если это может помочь, я использую PostgreSQL, и я ничего не меняю в конфигурации базы данных, slick или hikariCP (по крайней мере, для тестов) – Simon

1

Хотя это не дает ответа на то, что происходит с утечкой соединения, я, наконец, удалось взломать вокруг этого:

  1. Добавить JDBC к вам libraryDependencies, даже если Play-Slick FAQ говорит вам не делать его:

    # build.sbt 
    libraryDependencies += jdbc 
    

    Перезагрузите sbt, чтобы принять во внимание изменения. В IntelliJ вы также захотите обновить проект.

  2. Отключить JDBC модуль, который конфликтует с плей-скользкий (кредиты: this SO answer):

    # application.conf 
    play.modules.disabled += "play.api.db.DBModule" 
    

    На том же месте, вы должны быть уже настроен что-то вроде

    slick { 
        dbs { 
        default { 
         driver = "slick.driver.MySQLDriver$" 
         db.driver = "com.mysql.jdbc.Driver" 
         db.url = "jdbc:mysql://localhost/test" 
         db.user = "sa" 
         db.password = "" 
        } 
        } 
    } 
    
  3. Теперь вы можете использовать play.api.db.Databases от jdbc и его метод withDatabase для запуска эволюции s.

    import org.scalatest.BeforeAndAfterAll 
    import org.scalatestplus.play.PlaySpec 
    import play.api.db.{Database, Databases} 
    import play.api.db.evolutions.Evolutions 
    
    
    trait ResetDbSpec extends PlaySpec with BeforeAndAfterAll { 
    
        /** 
        * Here we use Databases.withDatabase to run evolutions without leaking connections. 
        * It slows down the tests considerably, though. 
        */ 
    
        private def withTestDatabase[T](block: Database => T) = { 
        Databases.withDatabase(
         driver = "com.mysql.jdbc.Driver", 
         url = "jdbc:mysql://localhost/test", 
         name = "default", 
         config = Map(
         "username" -> "sa", 
         "password" -> "" 
        ) 
        )(block) 
        } 
    
        override def beforeAll() = { 
        withTestDatabase { database => 
         Evolutions.applyEvolutions(database) 
        } 
        } 
    
        override def afterAll() = { 
        withTestDatabase { database => 
         Evolutions.cleanupEvolutions(database) 
        } 
        } 
    
    } 
    
  4. Наконец, тесты вызова, требующие перезагрузки дб, как это:

    class MySpec extends ResetDbSpec {...} 
    

Конечно, это отстой повторять этот конфиг как в "application.test.conf" и в withDatabase(), плюс он смешивает два разных API, не говоря о производительности. Также он добавляет это до и после каждого пакета, который раздражает:

[info] application - Creating Pool for datasource 'default'
[info] application - Shutting down connection pool.

Если кто-то есть лучшее предложение, пожалуйста улучшить этот ответ! Я много месяцев борется.

 Смежные вопросы

  • Нет связанных вопросов^_^