2017-05-12 1 views
1

"Dependency Injecting Actors"에는 자식 액터의 생성자에 매개 변수를 삽입하는 방법이 나와 있습니다. 부모 액터는 injectChild를 사용하여 자식 생성시에만 주입되지 않은 매개 변수를 전달하고 나머지는 Guice가 주입하도록 허용합니다. 이 작업을 수행하기 위해서는 InjectedActorSupport 확장하고 자녀의 생성자 주입 공장 가져옵니다 배우 그러나 사용자 정의 ApplicationLoader을 부모를 시작하지 않은 클래스에 대해사용자 지정 ApplicationLoader가 종속성 삽입 액터를 시작하고 테스트를 수행하려면 어떻게해야합니까?

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

그러나 무엇을? 거기에서 부모 액터를 시작하려면 어떻게해야합니까? 이것에 대한 언급은 문서에 없습니다.

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. 어떻게 Guice 필요 무슨 의존성 주입시키는 동안 MyLoader에서 부모를 시작합니까?
  2. MyLoader를 테스트하려면 어떻게해야합니까? 이것은 지금까지 내 테스트 였지만 이제는 주입 된 물건을 MyLoader에 전달해야하며 어떻게 해야할지 모르겠다.) 찾으려면

    클래스 MyLoaderSpec (_system는 : ActorSystem 암시 브로 EC : ExecutionContext에)이 매처 (Matchers) { 브로 로더 = 가진 BeforeAndAfterAll 새로운 SimstimLoader을 WordSpecLike와 TestKit (_system)를 연장 (???)

    def beforeAll() : Unit = { loader.load (ApplicationLoader.createContext (새 파일 ("."), ApplicationLoader.getClass.getClassLoader, Mode . 테스트))) }

미리 감사드립니다!

답변

0

다음은이 문제를 해결 한 방법입니다.

-> 의존성 주입이 필요한 상위 액터를 시작하는 방법. 우선, 나처럼 의존성을 필요로한다면 그러한 행위자를 수동으로 시작하는 것은 불가능합니다. 통과하는 법을 모르는 인스턴스를 삽입하고 어디에서 가져 왔는지. 해결책은 Guice가 자동으로 배우를 시작하도록하는 것입니다. 방법은 다음과 같습니다. 첫째, Guice을 위해 바인더 모듈을 만들 :

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은 단순히 의존성 주입 액터의 자동 시작이 실제로 발생할 때마다 로그하는 클래스입니다.나는이 때 확신 할 수 있도록 내가 이벤트를 기록하며 발생 여부 : 내 경우에는

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 메시지는 테스트 목적으로 고유하게 사용됩니다. 일반적으로 resultsVar 속성의 초기화 때문에 구성 구문 분석이 대신 발생합니다.

이렇게하면 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] 
     } 
    } 
    } 
} 

하고 나서 편리하게 구성 분석에 의한 바르 대신에 모의 객체를 제공하여 MyParent을 테스트

관련 문제