5

Play フレームワークでいくつかの単体テストを設定しようとしています。私のロジックの多くは、バックグラウンドでデータを収集するスケジュールされた akka アクターに組み込まれています。私の問題は、それらを単体テストする方法がわからないことです。私は文字通りそれにアプローチする方法がわかりません。akka-testkit を使おうとしているのですが、基本的にバタバタしています。それにアプローチする方法について何か提案はありますか?例は信じられないほど役に立ちます。これは、私が現在取り組んでいる嫌悪感の例です。

package test

import org.specs2.mutable._
import controllers.Scanner
import java.util.UUID
import org.joda.time.DateTime
import akka.testkit.TestActorRef
import play.api.Logger
import play.api.test.{FakeApplication, TestServer}
import models.PSqlEnum

class ScannerTest extends Specification {
  val appId = UUID.randomUUID()
  val app = models.App(appId, "TestApp", "TestServer", "TestComponent", "Test Description", DateTime.now(),
                       DateTime.now(), true, 3, 60, PSqlEnum("scanType", "mandatory"), "http://localhost")
  val rules = <Rule name="DivisionDataIsAvailable" elementsToCheck="DivisionDataIsAvailable"
                    ruleType="is, true, yellow" />
              <Rule name="DivisionDataLoadIsHealthy" elementsToCheck="DivisionDataLoadIsHealthy"
                    ruleType="is, true, red" />;

  "Scanner" should {
    "test something" in {
      val fakeApp = TestServer(3333)
      fakeApp.start()
      implicit val actorSystem = play.api.libs.concurrent.Akka.system(fakeApp.application)
      val scanner = TestActorRef(new Scanner(app, rules)).underlyingActor
      Logger.warn(scanner.getResponseFromWebService.toString)
      fakeApp.stop()
      1 === 1
    }
  }
}

これは明らかに実際には何もテストしていません。私は基本的に、実行時エラーを停止できるかどうかを確認するために、この時点で 1 === 1 に到達できるようにしようとしています。このコードが生成しているエラーは次のとおりです。

INFO  - Starting application default Akka system.
[info] ScannerTest
[info] Scanner should
[info] ! test something
[error]     ThrowableException: akka.actor.LocalActorRef.<init>(Lakka/actor/ActorSystemImpl;Lakka/actor/Props;Lakka/actor/InternalActorRef;Lakka/actor/ActorPath;)V (TestActorRef.scala:21)
[error] akka.testkit.TestActorRef.<init>(TestActorRef.scala:21)
[error] akka.testkit.TestActorRef$.apply(TestActorRef.scala:135)
[error] akka.testkit.TestActorRef$.apply(TestActorRef.scala:132)
[error] akka.testkit.TestActorRef$.apply(TestActorRef.scala:125)
[error] test.ScannerTest$$anonfun$1$$anonfun$apply$3.apply(ScannerTest.scala:27)
[error] test.ScannerTest$$anonfun$1$$anonfun$apply$3.apply(ScannerTest.scala:23)
[error] akka.actor.LocalActorRef.<init>(Lakka/actor/ActorSystemImpl;Lakka/actor/Props;Lakka/actor/InternalActorRef;Lakka/actor/ActorPath;)V
[error] akka.testkit.TestActorRef.<init>(TestActorRef.scala:21)
[error] akka.testkit.TestActorRef$.apply(TestActorRef.scala:135)
[error] akka.testkit.TestActorRef$.apply(TestActorRef.scala:132)
[error] akka.testkit.TestActorRef$.apply(TestActorRef.scala:125)
[error] test.ScannerTest$$anonfun$1$$anonfun$apply$3.apply(ScannerTest.scala:27)
[error] test.ScannerTest$$anonfun$1$$anonfun$apply$3.apply(ScannerTest.scala:23)
[info] Total for specification ScannerTest
[info] Finished in 86 ms
[info] 1 example, 0 failure, 1 error
[info] test.ScannerTest

FakeApplication を作成し、その FakeApplication の Akka.system を使用する必要があると思います。しかし、私はそれを行う方法がわかりません。正直なところ、それが正しいアプローチであるかどうかさえわかりません。汎用の Akka.system を生成してそれを機能させることができれば、私は有頂天になるでしょう。誰かがこれに取り組む方法について何かアイデアを持っているなら、私は本当に感謝しています.

4

3 に答える 3

10

わかりました。正しいバージョンの akka-testkit を使用していることを確認してください。Play 2.2.0 では、akka 2.2.M3 を使おうとしていました。明らかに、それはうまくいきません。Build.scala に正しい依存関係を配置する必要がありましたが、最終的には次のようになりました。

"com.typesafe.akka" %% "akka-testkit" % "2.2.0" % "test"

私の実際のテストコードは次のようになります。

package test

import org.specs2.mutable._
import controllers.Scanner
import java.util.UUID
import org.joda.time.DateTime
import akka.testkit.TestActorRef
import play.api.Logger
import models.PSqlEnum
import akka.actor.ActorSystem
import com.typesafe.config.ConfigFactory
import scala.concurrent.ExecutionContext.Implicits.global

class ScannerTest extends Specification {
  val appId = UUID.randomUUID()
  val app = models.App(appId, "TestApp", "TestServer", "TestComponent", "Test Description", DateTime.now(),
                       DateTime.now(), true, 3, 60, PSqlEnum("scanType", "mandatory"), "http://localhost")
  val rules = <Rule name="DivisionDataIsAvailable" elementsToCheck="DivisionDataIsAvailable"
                    ruleType="is, true, yellow" />
              <Rule name="DivisionDataLoadIsHealthy" elementsToCheck="DivisionDataLoadIsHealthy"
                    ruleType="is, true, red" />;


  "Scanner" should {
    "test something" in {
      implicit val actorSystem = ActorSystem("testActorSystem", ConfigFactory.load())
      val scanner = TestActorRef(new Scanner(app, rules)).underlyingActor
      val response = scanner.getResponseFromWebService
      response onSuccess {
        case result => Logger.warn(result.toString)
      }
      response onFailure {
        case error => Logger.warn(error.toString)
      }
      1 === 1
    }
  }
}

繰り返しますが、このテストは実際には何もしていません。評価される実際のテストは 1 === 1 です。現在はログに出力されていますが、これは、戻ってデータ型と応答のペイロードを確認し、実際の単体テストを作成できることを意味します。誰かがこれが役立つことを願っています。元の質問のこれらのエラー メッセージは、akka-testkit の依存関係が Akka と同じバージョンではないことが原因で発生しますが、これは誰かにとって役立つ可能性があります。

于 2013-10-03T10:24:02.930 に答える
0

私は ActorSystem("testActorSystem" ) を使用しません。プレイ フレームワークが通常の akka プラグインを使用できるようにしました。このアプローチには次の利点があります: すべてのコードで play.api.libs.concurrent.Akka.system を使用でき、ブースのプレイと akka コード部分を理解する追加の構成オプションを使用できます。

  class BaseActorTester (_app: Application) extends akka.testkit.TestKit(play.api.libs.concurrent.Akka.system(_app)) with FunSuiteLike with BeforeAndAfterAll {

   def this() = this(FakeApplication(additionalConfiguration=Map("currency.db"->"airando-test")))
   implicit val app: Application = _app
   implicit val ec = play.api.libs.concurrent.Akka.system.dispatcher

   override def beforeAll {
     Play.start(app)
   }
   // play plugin do it itself ??
   //override def afterAll {
   //  akka.testkit.TestKit.shutdownActorSystem(system)
   //}
   ...
  }
于 2014-09-07T18:34:47.327 に答える