2016-05-09 4 views
3

私はscala play 2.5を使用しています。コントローラの1つにオブジェクトを挿入しようとすると、次のエラーが発生します。 私はGuiceであるplayで与えられたデフォルトの注入フレームワークを使用しています。ここでScala play Guice injection

ProvisionException: Unable to provision, see the following errors: 
    1) No implementation for services.MyService was bound. 
    while locating services.MyService for parameter 0 at controllers.MyController.<init>(MyController.scala:12) 
    while locating controllers.MyController for parameter 3 at router.Routes.<init>(Routes.scala:55) 
    while locating router.Routes 
    while locating play.api.inject.RoutesProvider while locating play.api.routing.Router for parameter 0 at play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:200) 
    while locating play.api.http.JavaCompatibleHttpRequestHandler 
    while locating play.api.http.HttpRequestHandler for parameter 4 at play.api.DefaultApplication.<init>(Application.scala:221) at play.api.DefaultApplication.class(Application.scala:221) 
while locating play.api.DefaultApplication 
    while locating play.api.Application 

はコントローラである:ここでは

package controllers 

import services.MyService 

class MyController @Inject()(myService: MyService, val messagesApi: MessagesApi) extends Controller with I18nSupport { 

    def someFunctionThatUsesMyService(url: String) = Action {} 
} 

は私が注入したいサービスです。

package services 

import javax.inject._ 

trait MyService { 
    def op(param1: String, param2: String): Boolean 
} 

@Singleton 
class BasicMyService extends MyService { 
    override def op(param1: String, param2: String): Boolean = true 
} 

私はそれを使用していますどのようにしていること:

@Singleton 
class HomeController @Inject() extends Controller { 

    /** 
    * Create an Action to render an HTML page with a welcome message. 
    * The configuration in the `routes` file means that this method 
    * will be called when the application receives a `GET` request with 
    * a path of `/`. 
    */ 
    def index = Action { 
    //Ok(views.html.index("Your new application is ready.")) 
    Redirect(routes.MyController.someFunctionThatUsesMyService(Some(routes.OtherController.welcomePage().url))) 
    } 

} 

答えて

5

追加する必要があります。ImplementedBy annotatioトレイト

package services 

import javax.inject._ 

@ImplementedBy(classOf[BasicMyService]) 
trait MyService { 
    def op(param1: String, param2: String): Boolean 
} 

@Singleton 
class BasicMyService extends MyService { 
    override def op(param1: String, param2: String): Boolean = true 
} 
+0

あなたがMockedMyServiceのためにこれをどのように行うのですテストのためMyServiceでの拡張ここで

は、いくつかのコード

コントローラがあります目的?ファイルを読み込んでもBasicMyServiceが自動的にバインドされませんか? – dlite922

+0

なぜ抽象レイヤーがもう1層必要ですか?コントローラーに具体的な実装を注入し、必要に応じてテストに偽装してみませんか? – Sergey

0

にサービスを提供するために、nはあなたが直接サービスを注入しようとすることができ、なぜあなたはダミー形質のその層が必要なのですか?すべてのものは、余分なコーディングなしに箱の外で動作する必要があります。あなたは常にあなたの外部のdepsを微調整することができます。以下の例を参照してください。

class MyController @Inject()(service: SomeConcreteService) extends Controller { /** just use service.anyMethod here */ } 

サービス:

@Singleton 
class SomeConcreteService @Inject()(otherStuff: OtherStuffConcrete){ 
/** otherStuff will be also injected */ 
    def mySuperServiceMethod:={ "Hey!" } 
} 

テスト:

class MyControllerTest extends PlaySpec with OneAppPerSuite with MockitoSugar { 

    // do it this way if you want framework to provide controller instance 
    private val myController = app.injector.instanceOf[MyController] 

    // or mock external deps and build controller on your own 
    val externalService = mock[SomeConcreteService] 
    val handMadeController = new MyController(externalService) 

    "My controller" should{ 
     "do its best " in { 
      val response = call(handMadeController.doStuff, FakeRequest()) 

      status(response) mustBe OK 

      contentAsString(response) must include("Best controller") 

    } 
} 
関連する問題