2016-05-09 5 views
3

Я использую scala play 2.5, и у меня есть следующая ошибка при попытке вставить объект в один из моих контроллеров. Я использую стандартную инъекционную инфраструктуру, данную с игрой, которая представляет собой Guice.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 n до служебной черты

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

Зачем вам нужен еще один слой абстракции? Почему бы просто не вводить конкретные реализации в контроллер и не придумывать их при тестировании? – Sergey

0

Вы можете попробовать непосредственно внедрить услуги, зачем вам этот слой фиктивных черт? Все материалы должны работать вне коробки без дополнительного кодирования. Вы всегда можете точно настроить внешние депиляции. См. Пример ниже.

Вот код

Контроллер:

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") 

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