我对演员有一个例外,因为它在测试中是如何实现的。
我正在使用Play Scala 2.5和提供的akka库。
这是我的控制器:
class MyController @Inject()(implicit context: ExecutionContext, val messagesApi: MessagesApi, system: ActorSystem) extends Controller with I18nSupport {
val (out, channel) = Concurrent.broadcast[String]
val listenerActor = system.actorOf(Listener.props, "listener")
listenerActor ! Start(channel)
def stream = Action { implicit req =>
val source = Source.fromPublisher(Streams.enumeratorToPublisher(out))
Ok.chunked(source via EventSource.flow).as("text/event-stream")
}
def myAction = Action.async {
listenerActor ! NewMessage("Action myAction call")
}
}
这是我的演员:
object Listener {
def props = Props[Listener]
case class Start(out: Concurrent.Channel[String])
case class NewMessage(message: String)
}
class Listener extends Actor {
import Listener._
var out: Option[Concurrent.Channel[String]] = None
def receive = {
case Start(out) => this.out = Some(out)
case NewMessage(msg) => this.out.map(_.push("{ \"message\": \"" + msg + "\" }"))
}
}
我的测试:
class MyControllerSpec extends PlaySpec with OneAppPerSuite with ScalaFutures with MockitoSugar {
val messagesApi = app.injector.instanceOf[MessagesApi]
val ec = app.injector.instanceOf[ExecutionContext]
val actorSystem = app.injector.instanceOf[ActorSystem]
val injector = new GuiceInjectorBuilder()
.overrides(bind[MessagesApi].toInstance(messagesApi))
.overrides(bind[ExecutionContext].toInstance(ec))
.overrides(bind[ActorSystem].toInstance(actorSystem))
.injector
def myController = injector.instanceOf(classOf[MyController])
"MyController" should {...}
}
我的所有测试都失败,例外:
com.google.inject.ProvisionException: Unable to provision, see the following errors:
[info]
[info] 1) Error injecting constructor, akka.actor.InvalidActorNameException: actor name [listener] is not unique!
[info] at controllers.MyController.<init>(MyController.scala:29)
[info] while locating controllers.MyController
[info]
[info] 1 error
[info] at at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025)
[info] at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
[info] at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:405)
[info] at controllers.MyControllerSpec.myController(MyControllerSpec.scala:33)
[info] at controllers.MyControllerSpec$$anonfun$1$$anonfun$apply$mcV$sp$7.apply$mcV$sp(MyControllerSpec.scala:94)
[info] at controllers.MyControllerSpec$$anonfun$1$$anonfun$apply$mcV$sp$7.apply(MyControllerSpec.scala:92)
[info] at controllers.MyControllerSpec$$anonfun$1$$anonfun$apply$mcV$sp$7.apply(MyControllerSpec.scala:92)
[info] at org.scalatest.Transformer$$anonfun$apply$1.apply$mcV$sp(Transformer.scala:22)
[info] at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
[info] at org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
[info] ...
[info] Cause: akka.actor.InvalidActorNameException: actor name [listener] is not unique!
[info] at akka.actor.dungeon.ChildrenContainer$NormalChildrenContainer.reserve(ChildrenContainer.scala:130)
[info] at akka.actor.dungeon.Children$class.reserveChild(Children.scala:130)
[info] at akka.actor.ActorCell.reserveChild(ActorCell.scala:374)
[info] at akka.actor.dungeon.Children$class.makeChild(Children.scala:268)
[info] at akka.actor.dungeon.Children$class.attachChild(Children.scala:46)
[info] at akka.actor.ActorCell.attachChild(ActorCell.scala:374)
[info] at akka.actor.ActorSystemImpl.actorOf(ActorSystem.scala:591)
[info] at controllers.MyController.<init>(MyController.scala:34)
[info] at controllers.MyController$$FastClassByGuice$$5133fbab.newInstance(<generated>)
[info] at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
如何组织代码以便我的演员正确实现?
=============================================== ========================== 的更新 我修改了控制器代码以使其工作。它不再使用依赖注入。
class MyController @Inject()(implicit context: ExecutionContext, val messagesApi: MessagesApi) extends Controller with I18nSupport {
val (out, channel) = Concurrent.broadcast[String]
val listenerActor = ActorSystem("listener").actorOf(Props[Listener])
listenerActor ! Start(channel)
def stream = Action { implicit req =>
val source = Source.fromPublisher(Streams.enumeratorToPublisher(out))
Ok.chunked(source via EventSource.flow).as("text/event-stream")
}
def myAction = Action.async {
listenerActor ! NewMessage("Action myAction call")
}
}
删除在测试中注入ActorSystem的代码。
答案 0 :(得分:1)
ActorSystem("a name").actorOf(Props[youractor])
检查此代码是否可以帮助您,它需要一个简洁的名称。