2016-08-20 2 views
2

나는 수신 방법의 상태 전환을 시험하려고하고있다. 발견 this stackoverflow 게시물,하지만 또한 명확하게 솔루션을 제공하지 않습니다. 아래의 단순화 된 코드를 찾아주세요 : -깔끔한 방법으로 테스트해라. 스카치가 어색해진다.

package become_unbecome_basics 

import akka.actor.{Actor, ActorSystem} 
import akka.testkit.{ImplicitSender, TestActorRef, TestKit} 
import become_unbecome_basics.BasicBecomeUnbecomeActor.{SWITCH_TO_MASTER, SWITCH_TO_STANDBY} 
import com.typesafe.scalalogging.LazyLogging 
import org.scalatest.FlatSpecLike 
import org.scalatest.Matchers._ 

class BecomUnbecomeSwitchoverTest extends TestKit(ActorSystem("testSystem")) with ImplicitSender with FlatSpecLike{ 

    "initially receive" should "points to master" in { 
    val aRef = TestActorRef[BasicBecomeUnbecomeActor] 
    val actor = aRef.underlyingActor 

    //not sure, weather we have something like this to assert 
    //actor.receive should be(actor.master) 
    } 
} 

object BasicBecomeUnbecomeActor{ 
    case object SWITCH_TO_MASTER 
    case object SWITCH_TO_STANDBY 
} 

class BasicBecomeUnbecomeActor extends Actor with LazyLogging{ 
    override def receive: Receive = master 

    def master: Receive = { 
    case SWITCH_TO_STANDBY => 
     context.become(standBy) 

    case msg => logger.debug(s"master : $msg received") 
    } 

    def standBy: Receive = { 
    case SWITCH_TO_MASTER => 
     context.unbecome() 

    case msg => logger.debug(s"standBy : $msg received") 
    } 
} 
+0

'unbecome'을 시도하는 대신 [Akka Finite State Machine] (http://doc.akka.io/docs/akka/current/scala/fsm.html)을 사용해보십시오. –

답변

0

에 StackOverflow는 당신이 언급 한 게시 두 당신의 배우를 테스트 할 수있는 방법을 제안이 포함되어 있습니다.

  1. 다른 액터로 상태 변경 사항을 내 보냅니다.
  2. 상태 변경은 테스트하지 말고 배우의 동작을 테스트하십시오.

첫 번째 예에서는 모든 상태 변경시 배우에게서 정보를 전송할 수있는 방법이 있습니다. Akka에서는 상태 변경 정보를 액터 메시지로 전송하는 것이 자연스러운 방법입니다.

import akka.actor._ 
import akka.testkit._ 

class ExampleActor(notify: ActorRef) extends Actor with ActorLogging { 
    import ExampleActor.{Master, StandBy} 

    def receive: Receive = master 

    def master: Receive = { 
    case StandBy => 
     notify ! StandBy 
     context.become(standby) 

    case msg => 
     log.debug("received msg in master: {}", msg) 
    } 

    def standby: Receive = { 
    case Master => 
     notify ! Master 
     context.become(master) 

    case msg => 
     log.debug("received msg in standby: {}", msg) 
    } 
} 

object ExampleActor { 
    def props(notify: ActorRef): Props = Props(new ExampleActor(notify)) 

    case object Master 
    case object StandBy 
} 

class ExampleActorTest extends TestKit(ActorSystem("testSystem")) with FlatSpecLike { 

    "ExampleActor" should "move to stand by state" in { 
    val probe = TestProbe() 
    val actor = system.actorOf(ExampleActor.props(probe.ref)) 

    actor ! ExampleActor.StandBy 

    probe.expectMsg(ExampleActor.StandBy) 
    } 
} 

위 코드에서

(I 아직 코드를 실행하지 않은 코드의 오류에 대한 사과 정도)의 ExampleActor 어떤 상태 변경 지정된 액터 참조를 통지하는 상태 배우 . 이 옵션은 현재 상태를 검사하는 것이 아니라 상태 전이 로그를 검사 할 수 있습니다. 또한 알림 코드가 액터에 자동으로 추가되는 것이 아니라 액터에 수동으로 추가되기 때문에 상태 알림 코드에 버그를 도입 할 수 있습니다.

좀 더 사실적인 테스트를 위해 테스트 스타일을 asynchronous testing style으로 변경했습니다.

상태 변경 알림을 사용하면 액터가 전환되는 특정 상태에 대한 정보를 얻을 수 있지만 제대로 작동하는지 알려주지는 않습니다. 배우가 수행하는 상태 변경을 테스트하는 대신 배우 자체가 수행하는 작업을 테스트하는 방법은 무엇입니까? 이 예에서

class Accumulator extends Actor with ActorLogging { 

    import Accumulator._ 

    def receive: Receive = accumulatorReceive(0) 

    def accumulatorReceive(x: Int): Receive = { 
    case Add(i) => next(x + i) 
    case Remove(i) => next(x - i) 
    case Multiply(i) => next(x * i) 
    case Divide(i) => next(x/i) 
    case Get => sender() ! x 
    } 

    def next(x: Int) = context.become(accumulatorReceive(x)) 
} 

object Accumulator { 
    def props: Props = Props(new Accumulator) 

    case class Add(i: Int) 
    case class Remove(i: Int) 
    case class Multiply(i: Int) 
    case class Divide(i: Int) 
    case object Get 
} 

class AccumulatorTest extends TestKit(ActorSystem("testSystem")) with FlatSpecLike { 

    import Accumulator._ 

    "Accumulator" should "accumulate" in { 
    val probe = TestProbe() 
    val actor = system.actorOf(Accumulator.props) 

    actor ! Add(3) 
    actor ! Remove(1) 
    actor ! Multiply(4) 
    actor ! Divide(2) 

    probe.send(actor, Get) 
    probe.expectMsg(5) 
    } 
} 

, Accumulator 상태 변경을 수행하지만, 그 상태가 변경되었을 때 통지하지 않는다. 대신에 흥미로운 부분을 검사하기위한 특정 get 명령이 있습니다. 테스트에서 누적 액터의 상태 변경을 유발하는 여러 메시지를 보냅니다. 마지막으로 누적기를 쿼리하여 이러한 메시지의 결과를 검사합니다.