参见下面的单元测试。在单元测试本身内部和外部定义的Actor类在通过system.actorOf实例化时看起来表现不同,但仅在使用Akka文档中推荐的Props样式时(第67页,第3.1节,Akka Scala文档的Props 2.2版) 0.3)。
我声明两个简单的Greeter Actors,一个在内部,一个在规范之外,然后以两种不同的方式为每一个获取ActorRef - 一次使用不推荐使用的Props样式,一次使用推荐的Props样式。只有第[4]行抛出了IllegalArgumentException。
任何想法可能会发生什么?谢谢你的帮助!
(注意:同样的问题出现在使用FunSpec,所以WordSpec,MustMatchers似乎不是一个因素)
import org.junit.runner.RunWith
import org.scalatest.WordSpec
import org.scalatest.matchers.MustMatchers
import akka.actor.ActorSystem
import akka.actor.Props
import org.scalatest.junit.JUnitRunner
import akka.actor.Actor
class MyGreeter extends Actor {
def receive = {
case _ => println("greetings!")
}
}
@RunWith(classOf[JUnitRunner])
class HelloAkkaTest extends WordSpec with MustMatchers {
class MyOtherGreeter extends Actor {
def receive = {
case _ => println("greetings!")
}
}
"Greeter" must {
"greet" in {
val system = ActorSystem()
system.actorOf(Props[MyGreeter], "greeter") // [1] Works
system.actorOf(Props(new Greeter)) // [2] Works
system.actorOf(Props(new MyOtherGreeter)) // [3] Works
system.actorOf(Props[MyOtherGreeter], "other") // [4] Fails!
}
}
}
我使用scalatest 2.10-2.0-RC3与scala 2.10.2和akka 2.10-2.3.0-RC2
答案 0 :(得分:2)
您在这里面对的是scala和嵌套类的有趣细节。当你有像
这样的结构时class Foo {
class Bar
}
然后内部类Bar
将绑定到Foo的特定实例,这意味着您无法在此实例之外实例化它。
scala> new Foo
res5: Foo = Foo@5b2cef50
scala> new res5.Bar
res6: res5.Bar = Foo$Bar@64f8b658
scala> new Foo#Bar
<console>:12: error: Foo is not a legal prefix for a constructor
new Foo#Bar
^
Props.apply[A <: Actor]
隐式检索ClassTag[A]
的实例,然后尝试通过反射调用构造函数。那么让我们看一下Foo#Bar
的构造函数:
scala> classOf[Foo#Bar].getConstructors
res9: Array[java.lang.reflect.Constructor[_]] = Array(public Foo$Bar(Foo))
如您所见,它期望Foo
的实例作为参数。那么我们如何解决这个问题?
我的建议是将课程带到测试课程之外。有两种可能性,或者直接放在包装下面,作为你的另一个类,或者放在测试类的伴侣中。
解决此问题的另一种方法是将对测试类的引用传递给Props
:
system.actorOf(Props(classOf[MyOtherGreeter], this), "other")