Akka ActorのテストはTestKitをなるべく使おう
背景
アクターを使った部分のテストを書いていて、非同期処理でされることを意識していなかったせいでドハマリしたので、そのメモ
はまったパターン
ちょっとしたRestAPIを実装して、つぎのようなことをテストしたかったので、
- APIを呼び出し
- HogeActorにメッセージして、レスポンスを返す
- HogeActorでなんらかの処理がされる
下記のようなテストコードを書きました。
@Test
public void test() {
// 1. リクエスト実行
// 2. レスポンスが返ってくることを確認
assertThat(res).isNotEmpty();
// 3. HogeActorでされる処理の結果を取得
T actual = ...
// 4. 上記が期待通りか確認
assertThat(actual).isEqualTo(expected);
}
なにがまずいかというと、3
のHogeActorの処理は別スレッドで行われているので、このコードでは処理が終わったことが保障できないのです。(言われてみれば超あたりまえですが...)
短時間で終わることがわかりきっているなら、 TimeUnit.SECONDS.#sleep
で数秒待つのを差し込めば解消されますが、あまりよろしくはないです。
Actorはもともとマルチスレッドでやるためのようなものなので、このテストの方針がいけていないです。
対策
いわゆる、困難の分割です。テストの対象を、
- APIをたたいたら、期待したメッセージをHogeActorで受け取る
- HogeActorでメッセージを受信したら、期待する処理がされる
の2つに分けます。
1はJavaTestKitを使うのが向いています。
2はTestActorRefを使うのが向いています。これを使うと、通常は生成できないActorのインスタンスを取得できるので、onReceiveのメソッドをテストで直接使えるようになります。
あるいはメッセージの送信やメッセージの部分をモックにおきかえられるなら、
- APIを叩いたら、HogeActorにメッセージを送るメソッドがよばれる
- HogeActorにメッセージをわたしたら、期待する処理をするメソッドがよばれる
- 実際の処理を実行して、期待する結果かを確認
という風に、途中まではverifyでしのいで、やりたい処理のところだけを別途やるという作戦もあります。
マルチスレッドになっているときのテストは要注意ですね...
参考サイト
Author And Source
この問題について(Akka ActorのテストはTestKitをなるべく使おう), 我々は、より多くの情報をここで見つけました https://qiita.com/n_slender/items/f5659523c1bd23abaa0e著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .