我试图用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
答案 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强烈连接和管理的。这就是为什么在这种情况下您无法简单地覆盖Actor
与ActorRef
绑定进行测试的原因。