Akka FSM和TestKit将共享测试放入Trait使发送者成为deadLetters

时间:2014-11-30 16:19:03

标签: akka akka-testkit

我试图将一些常见的Akka FSM代码的常见测试纳入特征,但sender ref变为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]消息[java.lang.String]来自   TestActor [akka:// default / user / $$ b]来   演员[akka:// default / deadLetters]未送达。 [1]死信   遇到。可以使用关闭或调整此日志记录   配置设置' akka.log-dead-letters'和   ' akka.log止字母-期间关断'

如何修复隐式发送方以确保当FSM actor从特征中响应测试make的调用时它会返回testActor以使expectMsg有效?

1 个答案:

答案 0 :(得分: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

提供的测试中正确选择它