2016-01-05 5 views
9

私は、コンパイル時依存性注入とScalaTestでPlay 2.4.6を使用しています。コントローラのコンストラクタにはいくつかのパラメータがあり、ApplicationLoaderではそれを作成します。 は、ここでは、コードです:コンパイル時に使用するPlay 2.4.6の機能テストDI

class BootstrapLoader extends ApplicationLoader { 
    def load(context: Context) = { 
    new AppComponents(context).application 
    } 
} 

class AppComponents(context: Context) extends BuiltInComponentsFromContext(context) with NingWSComponents { 
    lazy val router = new Routes(httpErrorHandler, authenticationController, applicationController, assets) 
    lazy val applicationController = new controllers.Application() 
    lazy val authenticationController = new controllers.Authentication()(configuration, wsApi.client) 
    lazy val assets = new controllers.Assets(httpErrorHandler) 
} 

class Authentication(implicit configuration: Configuration, val ws: WSClient) extends Controller { 
    def login = Action { implicit request => 
    Unauthorized(s"${redirectUrl}") 
    } 
} 

class AuthenticationSpec extends PlaySpec with OneAppPerSuite { 

    implicit val configuration: Configuration = app.configuration 
    implicit val wsClient: WSClient = WS.client(app) 

    "when user not logged-in" should { 
    "return Status code Unauthorized(401) with redirect url" in { 
     1 mustEqual 2 
    } 
    } 
} 

私は、私は次のエラーを取得していますテスト実行しています:

[info] Exception encountered when attempting to run a suite with class name: controllers.AuthenticationSpec *** ABORTED *** 
[info] com.google.inject.ProvisionException: Unable to provision, see the following errors: 
[info] 
[info] 1) Could not find a suitable constructor in controllers.Authentication. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private. 
[info] at controllers.Authentication.class(Authentication.scala:19) 
[info] while locating controllers.Authentication 
[info]  for parameter 1 at router.Routes.<init>(Routes.scala:35) 
[info] while locating router.Routes 
[info] while locating play.api.test.FakeRouterProvider 
[info] while locating play.api.routing.Router 
[info] 
[info] 1 error 
[info] at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025) 
[info] at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051) 
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:321) 
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:316) 
[info] at play.api.Application$class.routes(Application.scala:112) 
[info] at play.api.test.FakeApplication.routes(Fakes.scala:197) 
[info] at play.api.Play$$anonfun$start$1.apply$mcV$sp(Play.scala:90) 
[info] at play.api.Play$$anonfun$start$1.apply(Play.scala:87) 
[info] at play.api.Play$$anonfun$start$1.apply(Play.scala:87) 
[info] at play.utils.Threads$.withContextClassLoader(Threads.scala:21) 

FakeApplication使用GuiceApplicationBuilder、もちろん動作しません。

このようなテストを実行するにはどうすればよいですか?テストはしてもアプリケーションを起動することはできませんので、あなたがエラーを取得している

おかげ

答えて

0

。これは、コントローラでDependency Injectionを使用しているため(エラーメッセージが示すように)、objectsの代わりにclassesと宣言する必要があるためです。あなたがdocsで見ることができるように:

package controllers 

import play.api.mvc._ 

class Application extends Controller { 
    def index = Action { 
     Ok("It works!") 
    } 
} 

をお使いのコントローラが注入されるいくつかの依存関係を持っている場合、あなたは、コントローラのコンストラクタで@Injectのアノテーションを使用する必要があります(もう一度、docsを参照してください)。インスタンスごとに:あなたは、ランタイムDIの代わりにそれを使用している場合

package controllers 

import play.api.mvc._ 
import play.api.libs.ws._ 
import javax.inject._ 

class Application @Inject() (ws: WSClient) extends Controller { 
    // ... 
} 

またCompile Time Dependency Injection docsを読むことができます。

+1

が、私は時間依存性注入をコンパイルする使用:ここscalatestを使用した例があるよう

が見えます。私はオブジェクトではなくクラスを使用しますが、実行時ではなくコンパイル時に注入を行いたいので、inject()を使用しないでください。質問にコントローラースケルトンを追加します。 – roterl

+0

@roterlあなた自身のアプリケーションローダーを設定しようとしましたか(https://www.playframework.com/documentation/2.4.x/ScalaCompileTimeDependencyInjection#Application-entry-point)? – marcospereira

+0

はい、私はそれを使用しています。彼は生産コードは動作しますが、テスト用に初期化する方法は見つけられません(FaceRequestなどで使用する) – roterl

0

を、私はあなたと同じ問題に直面しています

。私は満足のいく解決策を持っていない、次は単なる回避策です:。 は私WithApplicationLoaderクラスで

implicit def client:WSClient = NingWSClient() 

を入れてしまった私はまた、あなたがWS呼び出しを模擬することができますしかし、それは我々がここに欲しいものではありませんhttps://github.com/leanovate/play-mockwsを見つけ

1
override implicit lazy val app = new BootstrapLoader().load(
ApplicationLoader.createContext(
    new Environment(
    new File("."), ApplicationLoader.getClass.getClassLoader, Mode.Test))) 

それは2.5.1

+0

'BootstrapLoader'はどこにありますか?私はPlayのドキュメントでそれを見つけることができません。 – gregghz

関連する問題