1

こんにちは、仲間のコーダーと尊敬されている達人です。

Supervisorによって再起動される特定の状態 ( Busy ) にFSMある間、特定のメッセージで IOException をスローする必要があることを実装するアクターがあります。

抜粋:

case class ExceptionResonse(errorCode: Int)


when(Busy) {
    case ExceptionResponse(errorCode) =>
      throw new IOException(s"Request failed with error code $errorCode")
}

を使用してその動作をテストしようとしTestActorRefreceiveいますIOException

case class WhenInStateBusy() extends TestKit(ActorSystem()) with After {
  val myTestFSMRef = TestFSMRef(MyFSM.props)

  ...

  def prepare: Result = {
    // prepares tested actor by going through an initialization sequence
    // including 'expectMsgPfs' for several messages sent from the tested FSM
    // most of my test cases depend on the correctness of that initialization sequence

    // finishing with state busy
    myTestFSMRef.setState(Busy)

    awaitCond(
      myTestFSMRef.stateName == Busy, 
      maxDelay, 
      interval, 
      s"Actor must be in State 'Busy' to proceed, but is ${myTestFSMRef.stateName}"
    )
    success
  }

  def testCase = this {
    prepare and {
      myTestFSMRef.receive(ExceptionResponse(testedCode)) must throwAn[IOException]
    }
  }
}

注: 初期化シーケンスにより、テスト済みの FSM が完全に初期化され、内部可変状態が設定されていることが確認されます。状態Busyは、アクターが特定の種類のメッセージを受信した場合にのみ残すことができます。このメッセージは、私のテスト セットアップではテスト ケースによって提供される必要があるため、FSM が適切な状態にあると確信しています。

現在、私の Jenkins サーバー (Ubuntu 14.10) では、このテスト ケースは 20 回の試行のうち約 1 回で失敗します (-> 例外はスローされません)。しかし、私の開発マシン (Mac Os X 10.10.4) では、バグを再現できません。したがって、デバッガーは役に立ちません。

テストは順次実行され、各例の後にテスト システムがシャットダウンされます。

  • Java バージョン 1.7.0_71
  • Scala バージョン 2.11.4
  • アッカ バージョン 2.3.6
  • Specs2 バージョン 2.3.13

呼び出しがなぜmyTestActorRef.receive(ExceptionResponse(testedCode))結果にならないのか、誰でも説明できますExceptionか?

4

1 に答える 1

2

これは確かにトリッキーな質問です。私の主な疑いは、アクターがまだ初期化されていないことです。どうしてこれなの?system.actorOf( で使用される) を実装するTestFSMRef.apply()と、実際にアクターを開始する責任を負うエンティティは 1 つだけであり、それがその親であることが明らかになりました。私は多くの異なることを試しましたが、それらはすべて何らかの形で欠陥がありました.

しかし、それがどうしてこのテストを失敗させるのでしょうか?

基本的な答えは、あなたが示したコードでは、実行時setStateにFSMがすでに初期化されていることが保証されていないということです。特に (低電力の) Jenkins ボックスでは、ガーディアン アクターがかなりの時間実行されるようにスケジュールされていない可能性があります。その場合、FSM のステートメントは後で実行startWithされるため、オーバーライドされます。setState

これに対する解決策は、別のメッセージを FSM に送信し、 を呼び出す前に適切な応答を期待することsetStateです。

于 2015-08-15T07:21:06.617 に答える