2016-11-21 18 views
1

play2-reactivemongoでいくつかの機能テストを実行しようとしています。私は可能な限り具体的にしようとしますが、何かが欠けている場合は私に知らせてください。Play Framework 2.5 ApplicationLifecycle Guice Specs2のテスト

私はこのエラー

を取得し、テストを実行しようとすると私の依存関係がここに DaoSpecResources.scala

trait DaoSpecResources { 

    val timeout = DurationInt(10).seconds 

    val fakeApp = new GuiceApplicationBuilder() 
    .in(Mode.Test) 
    .configure(
     "play.modules.enabled" -> List("play.modules.reactivemongo.ReactiveMongoModule"), 
     "mongodb.uri" -> "mongodb://localhost:27017/test" 
    ) 
    .build 

    val reactiveMongoApi = fakeApp.injector.instanceOf[ReactiveMongoApi] 
    ... 
} 

libraryDependencies ++= Seq(
    cache, 
    "org.reactivemongo" %% "play2-reactivemongo" % "0.12.0", 
    "com.mohiva" %% "play-silhouette" % "4.0.0", 
    "com.mohiva" %% "play-silhouette-testkit" % "4.0.0" % "test", 
    specs2 % Test 
) 
MongoUserDao.scala

import play.modules.reactivemongo._ 
import play.modules.reactivemongo.json._ 
import reactivemongo.play.json.collection.JSONCollection 

class MongoUserDao @Inject() (val reactiveMongoApi: ReactiveMongoApi) extends UserDao { 
    val usersFuture = reactiveMongoApi.database.map(_.collection[JSONCollection]("users")) 
... 
} 

です

[error] cannot create an instance for class daos.UserDaoSpec 
[error] caused by com.google.inject.CreationException: Unable to create injector, see the following errors: 
[error] 
[error] 1) No implementation for play.api.inject.ApplicationLifecycle was bound. 
[error] while locating play.api.inject.ApplicationLifecycle 
[error]  for parameter 1 at services.ApplicationTimer.<init>(ApplicationTimer.scala:24) 
[error] at Module.configure(Module.scala:23) (via modules: com.google.inject.util.Modules$OverrideModule -> Module) 
[error] 
[error] 1 error 

答えて

2

これはapp/services/ApplicationTimer.scalaによって発生しますが、それはApplicationLifecycleに依存しますが、実装はApplicationLifecycleに限定されていません。 ApplicationTimerはすべての新しいPlayプロジェクトに含まれるデモです。必要ない場合は完全に削除するか、テストモードで実行している場合は少なくとも無効にする必要があります。 disabling modulesおよびoverriding modulesを参照してください。

ソリューション

DefaultReactiveMongoApiApplicationLifecycleに依存しているためしかし、あなたはApplicationLifecycleの実装への結合を提供する必要があります。最も簡単な方法:

import play.api.inject.{ ApplicationLifecycle, DefaultApplicationLifecycle } 
import play.api.inject.bind 

trait DaoSpecResources { 

    val timeout = DurationInt(10).seconds 

    val fakeApp = new GuiceApplicationBuilder() 
    .in(Mode.Test) 
    .configure(
     "play.modules.enabled" -> List("play.modules.reactivemongo.ReactiveMongoModule"), 
     "mongodb.uri" -> "mongodb://localhost:27017/test" 
    ) 
    .bindings(bind[ApplicationLifecycle].to[DefaultApplicationLifecycle]) 
    .build 

    val reactiveMongoApi = fakeApp.injector.instanceOf[ReactiveMongoApi] 

    val lifecycle = fakeApp.injector.instanceOf[DefaultApplicationLifecycle] 
    def stopApp = lifecycle.stop() 

} 

(追加5行:輸入、bindingslifecyclestopApp

その後、テスト仕様で、これと同じように、最後にstep(stopApp)を追加します。

class FooSpec extends PlaySpecification with DaoSpecResources { 

    // Your examples... 

    step(stopApp) 

} 

代替ソリューション

個人的には、 SpecificationまたはPlaySpecificationに拡張され、in this example from specs2 documentationのようにすべてを自動的に設定して解除する特別な特性。

trait PlayWithMongoSpecification extends PlaySpecification { 

    val timeout = DurationInt(10).seconds 

    val fakeApp = new GuiceApplicationBuilder() 
    .in(Mode.Test) 
    .configure(
     "play.modules.enabled" -> List("play.modules.reactivemongo.ReactiveMongoModule"), 
     "mongodb.uri" -> "mongodb://localhost:27017/test" 
    ) 
    .bindings(bind[ApplicationLifecycle].to[DefaultApplicationLifecycle]) 
    .build 

    val reactiveMongoApi = fakeApp.injector.instanceOf[ReactiveMongoApi] 

    val lifecycle = fakeApp.injector.instanceOf[DefaultApplicationLifecycle] 
    def stopApp = lifecycle.stop() 

    override def map(fs: =>Fragments) = fs^step(stopApp) 

} 

class FooSpec extends PlayWithMongoSpecification { 

    // Your examples... 

} 

あなたはreactiveMongoApilazy valを行うことを検討します。

+0

@Pawel_Bartkiewiczあなたの答えに感謝します。私はまだそれを解決しませんでした。 ReactiveMongoModuleの依存関係であるため、ApplicationLifeCycleが必要です。私は努力し続けます。 – agusgambina

+0

@agusgambina私の答えの2番目の部分はこれを考慮しました。私は、 'ApplicationLifecycle'の提供方法の例を詳細に説明しました。私のプロジェクトでこれをテストし、それがうまくいった。 –

+0

@Pawel_Bartkiewiczご回答いただきありがとうございます。あなたの代わりの解決策が本当に好きでした。私は本当にそれを動作させるようにしたが、できなかった。 play.modules.reactivemongo.DefaultReactiveMongoApiのデフォルトのコンストラクタにいくつかの設定を与えていないようです。正しいですか? – agusgambina

関連する問題