我正在尝试使用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并且有这项工作,我会欣喜若狂。如果有人对如何解决这个问题有任何想法我会非常感激。
答案 0 :(得分: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的版本不同引起的,这可能对某人有用。
答案 1 :(得分:0)
我没有使用spec2或Mockito,但这是我在Play 2.2.1中对Akka演员进行单元测试所做的事情:
import org.specs2.mutable.Specification
import scala.concurrent.duration._
import org.scalatest.concurrent._
import akka.testkit._
import org.scalatest.matchers.ShouldMatchers
import org.scalatest.{FlatSpec, BeforeAndAfterAll}
import akka.actor.{Props, ActorSystem}
import akka.pattern.ask
import akka.util.Timeout
import scala.util.{Failure, Success}
import model.BlacklistEntry
import scala.concurrent.{Future, Promise, Await}
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.test.FakeApplication
import model.BlacklistEntryImpl
class LicenceBlackListSpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with ShouldMatchers with FlatSpec with BeforeAndAfterAll {
play.api.Play.start(FakeApplication())
import akka.testkit.TestKit._
def this() = this( ActorSystem("LicenceBlackListSpec") )
override def afterAll: Unit = {
system.shutdown()
system.awaitTermination(10.seconds)
}
implicit val timeout = Timeout(10 seconds)
val blacklistRef = TestActorRef(Props[LicenceBlackList])
"An LicenceBlackList Actor" should "be able to create a new blacklist entry" in {
blacklistRef ! CreateEntry(BlacklistEntryImpl("NEW_KEY",1000,"Test creation"))
val expected: BlacklistEntry = BlacklistEntryImpl("NEW_KEY", 1000 ,"Test creation")
expectMsg( expected )
}
}
您需要将scalatest lib作为依赖项以及akka测试工具包包含在内:
&#34; org.scalatest&#34; %&#34; scalatest_2.10&#34; %&#34; 1.9.1&#34;
希望这会有所帮助。
答案 2 :(得分:0)
我不使用ActorSystem(“testActorSystem”),我试图让play框架使用它通常的akka插件。这种方法有以下好处:我可以在所有代码中使用play.api.libs.concurrent.Akka.system,我可以有额外的配置选项来理解booth play和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)
//}
...
}