2013-08-20 27 views
10

Tôi đang gặp sự cố với diễn viên mở rộng Stash và hoạt động hoàn toàn tốt khi khởi tạo nó với actorOf trong ActorSystem đơn giản. Bây giờ tôi thực sự muốn viết một số bài kiểm tra cho các diễn viên stashing của tôi trước khi sử dụng chúng trong chương trình của tôi. Nhưng tôi không thể tìm ra cách để sử dụng TestActorRef với tác nhân này trong bộ thử nghiệm của tôi.Thử nghiệm các diễn viên Akka trộn lẫn Stash với TestActorRef

Mã mà làm việc trông như thế này:

import akka.actor.{Stash, Actor, ActorSystem, Props} 
import com.typesafe.config.ConfigFactory 

object StashTest { 
    val config = ConfigFactory.parseString(
    """ 
     |akka.actor.default-mailbox { 
     | mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox" 
     |} 
    """.stripMargin) 
} 

class StashTestActor extends Stash { 

    def receive: Actor.Receive = { 
    case "unstash" => 
     unstashAll() 
     context become print 
    case msg => stash() 
    } 

    def print: Actor.Receive = { 
    case msg => println(s"Unstashed message: $msg") 
    } 
} 

val system = ActorSystem("stashSystem", StashTest.config) 
val ref = system.actorOf(Props[StashTestActor]) 

ref ! "stash me" 
ref ! "blah" 
ref ! "unstash" 

nào in

Unstashed message: stash me 

Unstashed message: blah 

Nhưng nếu tôi cố gắng viết một bài kiểm tra WordSpec cho nam diễn viên này, nó để lại tôi với một số trường hợp ngoại lệ khó chịu tôi có thể 't tìm ra những gì họ muốn tôi thay đổi trong mã của tôi.

lớp thử nghiệm sẽ như thế này

import akka.testkit.{TestActorRef, TestKit} 
import akka.actor.{Stash, Actor, ActorSystem} 
import org.scalatest.{WordSpecLike, MustMatchers} 
import com.typesafe.config.ConfigFactory 


class StashTestActor extends Stash { 

    def receive: Actor.Receive = { 
    case "unstash" => 
     unstashAll() 
     context become print 
    case msg => stash() 
    } 

    def print: Actor.Receive = { 
    case msg => println(s"Unstashed message: $msg") 
    } 
} 


class StashTest extends TestKit(ActorSystem("testSystem", StashTest.config)) 
with WordSpecLike 
with MustMatchers { 

    "A simple stashing actor" must { 
    val actorRef = TestActorRef[StashTestActor] 

    "stash messages" in { 
     actorRef ! "stash me!" 
    } 

    "unstash all messages" in { 
     actorRef ! "unstash" 
    } 
    } 
} 

object StashTest { 
    val config = ConfigFactory.parseString(
    """ 
     |akka.actor.default-mailbox { 
     | mailbox-type = "akka.dispatch.UnboundedDequeBasedMailbox" 
     |} 
    """.stripMargin) 
} 

Khi chạy thử nghiệm, tôi nhận được trường hợp ngoại lệ được ném trong instantiation của TestActorRef sau.

[ERROR] [08/20/2013 14:19:40.765] [testSystem-akka.actor.default-dispatcher-3] [akka://testSystem/user/$$a] Could not instantiate Actor 
Make sure Actor is NOT defined inside a class/trait, 
if so put it outside the class/trait, f.e. in a companion object, 
OR try to change: 'actorOf(Props[MyActor]' to 'actorOf(Props(new MyActor)'. 
akka.actor.ActorInitializationException: exception during creation 
    at akka.actor.ActorInitializationException$.apply(Actor.scala:218) 
    at akka.actor.ActorCell.create(ActorCell.scala:578) 
    at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:425) 
    at akka.actor.ActorCell.systemInvoke(ActorCell.scala:447) 
    at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:262) 
    at akka.testkit.CallingThreadDispatcher.process$1(CallingThreadDispatcher.scala:244) 
    at akka.testkit.CallingThreadDispatcher.runQueue(CallingThreadDispatcher.scala:284) 
    at akka.testkit.CallingThreadDispatcher.register(CallingThreadDispatcher.scala:153) 
    at akka.dispatch.MessageDispatcher.attach(AbstractDispatcher.scala:133) 
    at akka.actor.dungeon.Dispatch$class.start(Dispatch.scala:84) 
    at akka.actor.ActorCell.start(ActorCell.scala:338) 
    at akka.testkit.TestActorRef.<init>(TestActorRef.scala:50) 
    at akka.testkit.TestActorRef$.apply(TestActorRef.scala:141) 
    at akka.testkit.TestActorRef$.apply(TestActorRef.scala:137) 
    at akka.testkit.TestActorRef$.apply(TestActorRef.scala:146) 
    at akka.testkit.TestActorRef$.apply(TestActorRef.scala:144) 
    at stashActorTest.StashTest$$anonfun$1.apply$mcV$sp(StashTestActor.scala:29) 
    at stashActorTest.StashTest$$anonfun$1.apply(StashTestActor.scala:28) 
    at stashActorTest.StashTest$$anonfun$1.apply(StashTestActor.scala:28) 
    at org.scalatest.SuperEngine.registerNestedBranch(Engine.scala:613) 
    at org.scalatest.WordSpecLike$class.org$scalatest$WordSpecLike$$registerBranch(WordSpecLike.scala:120) 
    at org.scalatest.WordSpecLike$$anon$2.apply(WordSpecLike.scala:851) 
    at org.scalatest.words.MustVerb$StringMustWrapperForVerb$class.must(MustVerb.scala:189) 
    at org.scalatest.matchers.MustMatchers$StringMustWrapper.must(MustMatchers.scala:6167) 
    at stashActorTest.StashTest.<init>(StashTestActor.scala:28) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
    at java.lang.Class.newInstance(Class.java:374) 
    at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:444) 
    at sbt.TestRunner.runTest$1(TestFramework.scala:84) 
    at sbt.TestRunner.run(TestFramework.scala:94) 
    at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:224) 
    at sbt.TestFramework$$anon$2$$anonfun$$init$$1$$anonfun$apply$8.apply(TestFramework.scala:224) 
    at sbt.TestFramework$.sbt$TestFramework$$withContextLoader(TestFramework.scala:212) 
    at sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:224) 
    at sbt.TestFramework$$anon$2$$anonfun$$init$$1.apply(TestFramework.scala:224) 
    at sbt.TestFunction.apply(TestFramework.scala:229) 
    at sbt.Tests$$anonfun$7.apply(Tests.scala:196) 
    at sbt.Tests$$anonfun$7.apply(Tests.scala:196) 
    at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45) 
    at sbt.std.Transform$$anon$3$$anonfun$apply$2.apply(System.scala:45) 
    at sbt.std.Transform$$anon$4.work(System.scala:64) 
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237) 
    at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:237) 
    at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18) 
    at sbt.Execute.work(Execute.scala:244) 
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237) 
    at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:237) 
    at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:160) 
    at sbt.CompletionService$$anon$2.call(CompletionService.scala:30) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:724) 
Caused by: akka.actor.ActorInitializationException: Could not instantiate Actor 
Make sure Actor is NOT defined inside a class/trait, 
if so put it outside the class/trait, f.e. in a companion object, 
OR try to change: 'actorOf(Props[MyActor]' to 'actorOf(Props(new MyActor)'. 
    at akka.actor.ActorInitializationException$.apply(Actor.scala:218) 
    at akka.testkit.TestActorRef$$anonfun$apply$2$$anonfun$apply$1.applyOrElse(TestActorRef.scala:148) 
    at akka.testkit.TestActorRef$$anonfun$apply$2$$anonfun$apply$1.applyOrElse(TestActorRef.scala:147) 
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:33) 
    at scala.util.Failure$$anonfun$recover$1.apply(Try.scala:185) 
    at scala.util.Try$.apply(Try.scala:161) 
    at scala.util.Failure.recover(Try.scala:185) 
    at akka.testkit.TestActorRef$$anonfun$apply$2.apply(TestActorRef.scala:147) 
    at akka.testkit.TestActorRef$$anonfun$apply$2.apply(TestActorRef.scala:153) 
    at akka.actor.CreatorFunctionConsumer.produce(Props.scala:369) 
    at akka.actor.Props.newActor(Props.scala:323) 
    at akka.actor.ActorCell.newActor(ActorCell.scala:534) 
    at akka.actor.ActorCell.create(ActorCell.scala:560) 
    ... 58 more 
Caused by: java.lang.NullPointerException 
    at akka.actor.UnrestrictedStash$class.$init$(Stash.scala:82) 
    at stashActorTest.StashTestActor.<init>(StashTestActor.scala:9) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
    at akka.actor.ReflectiveDynamicAccess$$anonfun$createInstanceFor$2.apply(DynamicAccess.scala:78) 
    at scala.util.Try$.apply(Try.scala:161) 
    at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:73) 
    ... 64 more 

Tôi không gặp bất kỳ vấn đề nào với việc sử dụng TestActorRefs với các diễn viên không mở rộng Stash. Vì vậy, tôi không biết nếu nó là một lỗi cấu hình hoặc cái gì khác tôi đang mất tích.

Trả lời

2

tôi đã có thể kiểm tra các diễn viên với Stash như thế này:

val actor = TestActorRef(Props(new MyActorWithStash()).withDispatcher("deque")) 
2

Sử dụng phối AKKA mặc định cho phép tôi sử dụng StashTestActorRef:

val myActor = TestActorRef[MyActor](Props(classOf[MyActor]).withDispatcher("akka.actor.default-dispatcher")) 

Lưu ý rằng điều này có nghĩa các bài kiểm tra của bạn sẽ không còn sử dụng mặc định CallingThreadDispatcher và sẽ mất các lợi ích được đánh dấu in the akka docs

Các vấn đề liên quan