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)
}

然后我可以使用重复的测试代码在两个规范中测试两个状态的通用代码:

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

解决此问题的一种方法是对您的共同特征进行轻微的重新设计,如下所示:

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")
  }
}

如果您定义了隐式发件人,testCommonBehavior那么您可以放心,它会从您的测试中正确获取它,从而使其通过ImplicitSender

于 2014-12-01T18:57:47.673 回答