2017-05-12 20 views
1

在「Dependency Injecting Actors」中顯示瞭如何將參數注入到子actor的構造函數中。父母使用injectChild被允許傳遞給孩子(在孩子創建時)只有非注入的參數,然後讓Guice注入其餘的。要做到這一點,它擴展InjectedActorSupport並得到孩子的工廠在構造函數中注入:自定義ApplicationLoader如何啓動Dependency注入Actor並進行測試?

class MyParent @Inject() (childFactory: MyChild.Factory, 
          @Assisted something: Something, 
          @Assisted somethingElse: SomethingElse) extends Actor with InjectedActorSupport 
[..] 
    val child: ActorRef = injectedChild(childFactory(something, somethingElse), childName) 

但是,我們啓動了父母,而不是一個演員,但一個自定義ApplicationLoader類? 如何從那裏啓動父母演員?文件中沒有提到這一點。

我試圖做同樣的裝載機,像我一樣的家長:

class MyLoader @Inject() (parentFactory: MyParent.Factory) extends ApplicationLoader with Actor with InjectedActorSupport { 
[..] 
val parent = injectedChild(parentFactory(something, somethingElse), parentName) 

這會是正確的嗎?我如何測試它?

class MyModule extends AbstractModule with AkkaGuiceSupport { 
    def configure = { 
    bindActor[MyParent](parentName) 
    bindActor[MyLoader](loaderName) 
    bindActorFactory[MyChild, MyChild.Factory] 
    bindActorFactory[MyParent, MyParent.Factory] 
    } 
} 

所以:

  1. 我該如何開始從MyLoader同時讓吉斯依賴,注入真實需要什麼樣的父母?
  2. 我該如何測試MyLoader? 到目前爲止,這是我的測試,但現在我需要將注入的東西傳遞給MyLoader,我不知道如何(注意*** ??? ****代替我不知道哪裏的參數查找):

    類MyLoaderSpec(_SYSTEM:ActorSystem,隱VAL EC:的ExecutionContext)延伸TestKit(_SYSTEM)與WordSpecLike與BeforeAndAfterAll與匹配器{ VAL裝載機=新SimstimLoader(???

    覆蓋def beforeAll():Unit = {loader.load(ApplicationLoader.createContext(new Environment(new File(「。」),ApplicationLoader.getClass.getClassLoader,Mode 。))) }

非常感謝!

回答

0

這是我如何解決這個問題。

- >如何啓動需要依賴注入的父代。 首先,如果你像我一樣,需要依賴注入一個你不知道如何傳遞的實例以及從哪裏來,那麼手動啓動這樣一個actor是不可能的。解決辦法是讓Guice自動啓動actor。這是如何。 首先,創建您的粘合劑模塊吉斯:

class MyModule extends AbstractModule with AkkaGuiceSupport{ 

    override def configure(): Unit = { 
    bindActor[Root](Root.NAME) 
    bind(classOf[StartupActors]).asEagerSingleton() 
    } 
} 

然後,告訴遊戲中加入以下在你的conf/application.conf您的料組件位於:

play.modules={ 
    enabled += "my.path.to.MyModule" 
} 

的StartupActors僅僅是一個類我用來記錄每當實際發生依賴注入actor的automagic開始。我記錄事件,這樣我可以肯定的時候,以及是否它發生:在我的情況

class StartupActors @Inject() (@Named(Root.NAME) root: ActorRef) { 
    play.api.Logger.info(s"Initialised $root") 
} 

根演員需要解析自定義配置的照顧。由於從分析產生的增值經銷商由我的父母的演員,我需要模擬這樣產生的增值經銷商在測試過程中需要的,我委託解析到比母體演員以外的演員,即根演員:

object Root { 
    final val NAME = "THERoot" 
    case class ParseConfiguration() 
} 

class Root @Inject()(configuration: Configuration, projectDAO: ProjectDAO) extends Actor { 
    val resultingVar: Something = myConfigParsing() 

    override def preStart(): Unit = { 
    context.actorOf(Props(new MyParent(resultingVar: Something, somethingElse: SomethingElse, projectDAO: ProjectDAO))) 
    } 

    override def receive: Receive = { 
    case ParseConfiguration => sender ! myConfigParsing() 
    case _ => logger.error("Root actor received an unsupported message") 
    } 
} 

ParseConfiguration消息是唯一用於測試目的。通常情況下,配置解析是由於對結果變量屬性的初始化而發生的。

這樣,MyParent不會需要注入任何東西。只有StartupActors和Root會被注入。 MyParent只會從Root獲得projectDAO並將其傳遞給它的所有子項。

class MyParent(something: Something, somethingElse: SomethingElse, projectDAO: ProjectDAO) extends Actor { ... } 

最後完成,我怎麼寫的測試,因爲我有很多麻煩解決這個網上找到足夠的信息,以及報告在這裏。

import akka.actor.{ActorRef, ActorSystem, Props} 
import akka.testkit.{TestKit, TestProbe} 
import org.mockito.Mockito 
import org.mockito.Mockito._ 
import org.scalatest.{BeforeAndAfterAll, WordSpecLike} 
import org.specs2.matcher.MustMatchers 
import scala.concurrent.ExecutionContext.Implicits.global 
import scala.concurrent.{ExecutionContext, Future} 

case class AnyProjectAPI(val projectAPI: ProjectAPI) extends AnyVal 
class MyParentSpec(_system: ActorSystem, implicit val ec: ExecutionContext) extends TestKit(_system) 
    with WordSpecLike with BeforeAndAfterAll with MustMatchers { 
    val something = mock(classOf[Something]) 
    val somethingElse = mock(classOf[somethingElse]) 
    val projectDAOMock: ProjectDAO = mock(classOf[ProjectDAO]) 

    val projectTest: ProjectAPI = new ProjectAPI(allMyRandomConstructorArguments), 
    val projectsList: List[ProjectAPI] = List(projectTest) 
    val expectedCreationId = 1 
    private var parent: ActorRef = _ 

    def this() = this(ActorSystem("MySpec"), scala.concurrent.ExecutionContext.global) 

    override def afterAll: Unit = { 
    system.shutdown() 
    } 

    override def beforeAll(): Unit = { 
    parent = system.actorOf(Props(new MyParent(something, somethingElse, projectDAOMock)), MyParent.NAME) 
    } 

    "MyParentTesting: parent's pull request" should { 
    when(myProjApi.getAllProjects).thenReturn(Future {projectsList}) 
    val anyProject: AnyProjectAPI = AnyProjectAPI(org.mockito.Matchers.any[ProjectAPI]) 
    Mockito.when(projectDAOMock.create(org.mockito.Matchers.any[ProjectAPI])) 
     .thenReturn(Future {expectedCreationId}: Future[Int]) 
    val probe = TestProbe() 
    val probe1 = TestProbe() 

    "be successfully satisfied by all children when multiple senders are waiting for an answer" in { 
     probe.send(parent, UpdateProjects) 
     probe1.send(parent, UpdateProjects) 
     allChildren.foreach(child => 
     probe.expectMsg(expectedCreationId)) 
     allChildren.foreach(child => 
     probe1.expectMsg(expectedCreationId)) 
    } 
    } 
} 

import akka.actor.{ActorRef, ActorSystem, Props} 
import akka.testkit.{TestKit, TestProbe} 
import com.typesafe.config.ConfigFactory 
import org.mockito.Mockito.mock 
import org.scalatest.{BeforeAndAfterAll, WordSpecLike} 
import org.specs2.matcher.MustMatchers 
import play.api.Configuration 
import scala.concurrent.ExecutionContext 

class RootSpec(_system: ActorSystem) extends TestKit(_system) 
    with WordSpecLike with BeforeAndAfterAll with MustMatchers { 

    implicit val ec: ExecutionContext = scala.concurrent.ExecutionContext.global 
    val conf: com.typesafe.config.Config = ConfigFactory.load() 
    val configuration: Configuration = Configuration(conf) 
    val projectDAOMock: ProjectDAO = mock(classOf[ProjectDAO]) 

    private var mainActor: ActorRef = _ 
    private var something: Something = Something.empty 

    def this() = this(ActorSystem("MySpec")) 

    override def afterAll: Unit = { 
    system.shutdown() 
    } 

    override def beforeAll(): Unit = { 
    mainActor = system.actorOf(Props(new Root(configuration, projectDAOMock)), Root.NAME) 
    } 

    "RootSpec: Root Actor" should { 
    val probe = TestProbe() 

    "successfully parse the configuration file" in { 
     probe.send(mainActor, ParseConfiguration) 
     something = probe.expectMsgPF() { 
     case msg => msg.asInstanceOf[Something] 
     } 
    } 
    } 
} 

,然後我通過代替從配置解析所得VARS的方便提供模擬對象測試MyParent

相關問題