演员和单元测试

杰罗姆

由于在测试中如何体现,我对演员有一个例外。

我正在使用带有提供的akka​​库的Play Scala 2.5。

这是我的控制器:

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的代码。

詹金
ActorSystem("a name").actorOf(Props[youractor])

检查此代码是否可以帮助您,它是否需要合同名称。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章