斯卡尔迪:绑定[T< AkkaInjectable]到TestProbe.ref

时间:2015-10-21 15:34:34

标签: scala playframework akka akka-testkit scaldi

我试图用Scaldi测试Play 2.4应用程序中的Actor A。这个演员正在调用injectActorRef[B],我想用TestKit.TestProbe来模拟。

在我的specs2中,我希望能够在为演员B提供相应的TestKit.TestProbe.ref的同时检索模拟A的探测。

我想做这样的事情:

implicit val inj = (new TestModule(){
    bind[TestProbe] identifiedBy 'probeForB to TestProbe()
    bind[B] to inject[TestProbe]('probeForB).ref
}).injector

inject[TestProbe]('probeForB).expectMsgType[] must ...

问题是引用是ActorRef,因此与预期的B类型不匹配。

有干净的方法吗? 我们可以指定injectActorRef[B]返回的ActorRef吗?

我最终覆盖了Actor A的绑定。

val probeForB = TestProbe()

implicit val inj = (new Module() {
    bind[A] to new A() {
       override def injectB(): ActorRef = probeForB.ref
    }
 }).injector

1 个答案:

答案 0 :(得分:1)

正如您所提到的,问题是inject[TestProbe]('probeForB).ref为您提供ActorRef而不是实际演员的实例。

如果您想以您描述的方式测试它,那么您还需要为actor ActorRef定义B的绑定。例如:

bind [BActor] toProvider new BActor
bind [ActorRef] identifiedBy 'bRef to {
  implicit val system = inject [ActorSystem]
  injectActorRef[BActor]
}

进行此设置后,您可以使用测试探针覆盖第二个绑定:

bind [ActorRef] identifiedBy 'bRef to inject[TestProbe]('probeForB).ref

请注意,这个例子不是直接等效的,因为BActor现在有一个不同的主管(监护人,这就是我们需要在这里注入ActorSystem的原因)。

injectActorRef将演员创作委托给" context" ({1}}的父母演员或演员系统。它有用的是它创建了一个特殊的context.actorOf,当akka想要创建一个Props类时,它会注入新的BActor类实例。这意味着scaldi无法控制actor的生命周期(它非常重要,因为akka本身有非常复杂的机制),它只是给akka知道如何创建特定actor类的新实例。

如果你在另一个演员中创建一个演员(就像你描述的那样),那么他们的生命周期都是由akka强烈连接和管理的。这就是为什么在这种情况下您无法简单地覆盖ActorActorRef绑定进行测试的原因。