0

一般的な Akka FSM コードのいくつかの一般的なテストをトレイトに分解しようとしていますが、senderref はdeadLetters. この FSM コードの使用:

import akka.actor.FSM
import akka.testkit.TestFSMRef
import akka.testkit.TestKit
import akka.actor.ActorSystem
import org.scalatest.Matchers
import org.scalatest.WordSpecLike
import akka.testkit.ImplicitSender

sealed trait MyState
case object StateA extends MyState
case object StateB extends MyState

case class MyData(ignored: Option[Int] = None)

class MyFSM extends FSM[MyState, MyData] {
  startWith(StateA, MyData())

  val common: StateFunction = {
    case Event(_, _) =>
      System.err.println(s"sender is $sender")
      sender ! s"hello $stateName"
      stay
  }

  when(StateA)(common)

  when(StateB)(common)
}

次に、以下を使用して、テスト コードを複製して、2 つの仕様で共通コードを 2 つの状態にテストできます。

class StateASpec extends TestKit(ActorSystem()) with WordSpecLike with Matchers with ImplicitSender {

  def testCommonBehaviour(testState: MyState) {
    val fsm = TestFSMRef(new MyFSM())
    fsm.setState(testState, MyData())
    fsm ! "hello fsm"
    expectMsg("hello StateA")
  }

  "StateA" should {
    "respond to common test case" in {
      testCommonBehaviour(StateA)
    }
  }
}

class StateBSpec extends TestKit(ActorSystem()) with WordSpecLike with Matchers with ImplicitSender {

  def testCommonBehaviour(testState: MyState) {
    val fsm = TestFSMRef(new MyFSM())
    fsm.setState(testState, MyData())
    fsm ! "hello fsm"
    expectMsg("hello StateB")
  }

  "StateB" should {
    "respond to common test case" in {
      testCommonBehaviour(StateB)
    }
  }
}

一般的なテストロジックをトレイトに反応させようとすると、次のようになります。

trait TraitOfTests {
  self: TestKit with ImplicitSender =>

  def testCommonBehaviour(testState: MyState) {
    val fsm = TestFSMRef(new MyFSM())
    fsm.setState(testState, MyData())
    fsm ! "hello fsm"
    expectMsg("hello $testState")
  }
}

class StateASpec extends TestKit(ActorSystem()) with WordSpecLike with Matchers with ImplicitSender  with TraitOfTests {

  "StateA" should {
    "respond to common test case" in {
      testCommonBehaviour(StateA)
    }
  }
}

class StateBSpec extends TestKit(ActorSystem()) with WordSpecLike with Matchers with ImplicitSender  with TraitOfTests {

  "StateB" should {
    "respond to common test case" in {
      testCommonBehaviour(StateB)
    }
  }
}

応答は、deadLetters アクターに送られます。

送信者は Actor[akka://default/deadLetters] [INFO] [11/30/2014 16:15:49.812] [default-akka.actor.default-dispatcher-2] [akka://default/deadLetters] メッセージですTestActor[akka://default/user/$$b] から Actor[akka://default/deadLetters] への [java.lang.String] が配信されませんでした。[1] デッドレターが発生しました。このロギングは、構成設定 'akka.log-dead-letters' および 'akka.log-dead-letters-during-shutdown' でオフにするか、調整することができます。

FSM アクターがトレイト内からのテスト make の呼び出しに応答したときに、testActor に戻って動作するように、暗黙的な送信者を修正するにはどうすればよいexpectMsgですか?

4

1 に答える 1

0

この問題を解決する 1 つの方法は、次のように一般的な特性をわずかに再設計することです。

trait TraitOfTests {
  self: TestKit =>

  def testCommonBehaviour(testState: MyState)(implicit sender:ActorRef) {
    val fsm = TestFSMRef(new MyFSM())
    fsm.setState(testState, MyData())
    fsm ! "hello fsm"
    expectMsg("hello $testState")
  }
}

暗黙的な送信者を on に定義するtestCommonBehaviorと、それを使用可能にするテストから適切に取得されることが保証されます。ImplicitSender

于 2014-12-01T18:57:47.673 に答える