2016-12-25 14 views
9

私はPlaySlickを使用してデータベースに接続する以下のDAOを持っています。クラスにはScalaTestでテストする必要があるメソッドreadがあります。私の問題は、DatabaseConfigProviderを模擬してUsersDAOクラスに注入し、readメソッドをテストする方法を知らないということです。これはテストのクラスです:ScalaTestでのPlaySlickデータベース接続の挿入

class UsersDAO @Inject()(@NamedDatabase("mydb") 
      protected val dbConfigProvider: DatabaseConfigProvider) 
      extends with HasDatabaseConfigProvider[JdbcProfile] { 

    import driver.api._ 

    val db1 = dbConfigProvider.get[JdbcProfile].db 

    def read (sk: Int) = { 
     val users = TableQuery[UserDB] 
     val action = users.filter(_.sk === sk).result 
     val future = db1.run(action.asTry) 
     future.map{ 
     case Success(s) => 
      if (s.length>0) 
      Some(s(0)) 
      else 
      None 
     case Failure(e) => throw new Exception ("Failure: " + e.getMessage) 
     } 
    } 

} 

、これはテストを書くための私の試みです:

class UserDAOTest extends PlaySpec with OneAppPerSuite { 

    implicit override lazy val app = new GuiceApplicationBuilder(). 
    configure(
      Configuration.from(
       Map(
        "slick.dbs.mydb.driver" -> "slick.driver.MySQLDriver$", 
        "slick.dbs.mydb.db.driver" -> "com.mysql.jdbc.Driver", 
        "slick.dbs.mydb.db.url" -> "jdbc:mysql://localhost:3306/control", 
        "slick.dbs.mydb.db.user" -> "root", 
        "slick.dbs.mydb.db.password" -> "xxxxx" 
       ) 
      ) 
     ).build 

    val dbConfigProvider = app.injector.instanceOf[DatabaseConfigProvider] 

    "Example " should { 
    "be valid" in { 

     val controller = new UsersDAO(dbConfigProvider) 
     val result = controller.read(1) 
     println(result) 
    } 
    } 

私はそれが次のエラーメッセージで失敗したテストを実行する場合:

com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for play.api.db.slick.DatabaseConfigProvider was bound. while locating play.api.db.slick.DatabaseConfigProvider

+0

正確に同じ問題で苦労=> http://stackoverflow.com/questions/41369252/scala-play-and-scalatest-directory-structure-mismatch –

+0

'DatabaseConfigProvider.get [JdbcProfile](" mydb ")'? –

+0

@ insan-eこれはエラーを投げます: 'type mismatch;見つかりました:slick.backend.DatabaseConfig [slick.driver.JdbcProfile]必須:play.api.db.slick.DatabaseConfigProvider' – ps0604

答えて

4

IMHOでは、Playの注入物を妨害するのではなく、使用することをお勧めします。これは動作するはずです:

class UserDAOTest extends PlaySpec with OneAppPerSuite with ScalaFutures { 

    implicit override lazy val app = new GuiceApplicationBuilder(). 
    configure(
     "slick.dbs.mydb.driver" -> "slick.driver.MySQLDriver$", 
     "slick.dbs.mydb.db.driver" -> "com.mysql.jdbc.Driver", 
     "slick.dbs.mydb.db.url" -> "jdbc:mysql://localhost:3306/control", 
     "slick.dbs.mydb.db.user" -> "root", 
     "slick.dbs.mydb.db.password" -> "xxxxx").build 

    def userDAO(implicit app: Application): UserDAO = Application.instanceCache[UserDAO].apply(app) 

    "UserDAO" should { 
    "do whatever" in { 
     whenReady(userDAO.read(1)) { res => 
     println(res) 
     } 
    } 
    } 

} 

私は私が何かを逃した場合には、私のrepoを更新しました。

+0

OneAppPerSuiteを使用するコードサンプルでは、​​1つのアプリケーションで複数のテストスイートを実行できますか? –

+0

私はそれを試したことはありませんが、うまくいくはずです...これらのスイートを手動でグループ化し( '@ DoNotDiscover'を入れて)、この例を見てください:http://stackoverflow.com/questions/15423337/すべてのスケーラテスト前または後のテスト –

3

私はあなたのテストからデータベースを模倣したいと思っているのか、単に別のデータベース設定を使用するのか確信していません。

コードサンプルを見ると、私は後者を想定しています。

あなたが始めたとして、あなたが本当にそれをしたいと思った場合は、最も簡単な解決策は、このようになります:

// instead of your line below 
// val dbConfigProvider = app.injector.instanceOf[DatabaseConfigProvider] 
// use this: 
    val userDao = app.injector.instanceOf[UsersDao] 

上記は、あなたのDAOを注入し、暗黙のうちにあなたのDatabaseConfigProviderに対処します。

しかし、私はここに一つのことを理解していない - なぜあなたはこのような内容でテストリソースに別の構成(application.conf)を作成していない:ちょうどあなたのapp作成を変更するこれをやった後

slick.dbs.mydb.driver="slick.driver.MySQLDriver$" 
slick.dbs.mydb.db.driver="com.mysql.jdbc.Driver" 
slick.dbs.mydb.db.url = "jdbc:mysql://localhost:3306/control" 
slick.dbs.mydb.db.user=root 
slick.dbs.mydb.db.password="xxxxx" 

implicit override lazy val app = new GuiceApplicationBuilder().build 

とちょうど通常(上記と同様)は、このようなUsersDaoを注入:

これ

(私はあなたがテストとアプリケーションで異なるdb設定をしていることを前提としています)。

フルコード

テスト/リソース/ application.conf

slick.dbs.mydb.driver="slick.driver.MySQLDriver$" 
slick.dbs.mydb.db.driver="com.mysql.jdbc.Driver" 
slick.dbs.mydb.db.url = "jdbc:mysql://localhost:3306/control" 
slick.dbs.mydb.db.user=root 
slick.dbs.mydb.db.password="xxxxx" 

UserDaoTest.scala

import scala.concurrent.Await 
import scala.concurrent.duration.DurationInt 
//... other imports 

class UserDAOTest extends PlaySpec with OneAppPerSuite { 

    implicit override lazy val app = new GuiceApplicationBuilder().build 

    val userDao = app.injector.instanceOf[UsersDao] 

    "Example " should { 
    "be valid" in { 
     val result = userDao.read(1) 
     println(Await.result(result), 1.second) 

     // would be better to use whenReady from org.scalatest.concurrent.Futures 
     // but it's not really related to this question that much 
    } 
    } 
} 

概要

ここでは結論は手でオブジェクトを作成することを避けることです(最初のアプローチ - パラメータ付きのコンストラクタでUsersDaoを作成するのと同じです)。あなたがそれをする必要がない場合(時々そうする - いくつかのパラメータを変更したいときなど)、オブジェクト構造全体をDIに委譲する方が簡単です(例えば、UsersDaoをすべての依存関係注射した)。

+0

あなたの最初の解決策は動作していません、それは 'タイプの不一致を投げている;見つかった:slick.backend.DatabaseConfig [slick.driver.JdbcProfile] required:play.api.db.slick.DatabaseConfigProvider' – ps0604

+0

2番目の解決策に関して、私は 'application.conf'でdbを設定することができましたが、 daoにdb構成を挿入しますか?私がScalaTestを使用していることを覚えておいてください。 – ps0604

+0

あなたは完全な答えを今すぐ持っています。間違いがあったのですが、今は魅力的に働くでしょう。 –

関連する問題