2

我目前正在测试一个 akka 应用程序。我遇到了某种模式:我想测试 aTestProbe是否收到了某个消息,以某些字段为模。

例如,如果消息是:

UserInfo(username: String, score: Int, timestamp: String)

然后我可能想测试usernameandscore是否符合预期,但不在乎何时收到消息。

目前我想写这样的东西:

testProbe.expectMsgPF() {
  case UserInfo(`username`, `score`, _) =>
}

如何扩展测试探针类以便可以编写类似的东西?

testProbe.expectApproxMsg(UserInfo(`username`, `score`, _))

除了缩短我的代码之外,我希望这个问题的答案能进一步加深我对 Scala 编程语言的理解。

4

1 回答 1

0

我认为你不能做这样的事情

testProbe.expectApproxMsg(UserInfo(`username`, `score`, _))

因为,第一个最后一个属性(时间戳)不是var一个val需要有值的,如果你想要的是通过参数传递一个模式,你也不能,因为我们不能在没有所有case替代方案的情况下单独传递模式(PartialFunction)。

所以UserInfo(用户名,分数, _)是一个对象,一个普通的实例。

但是我们可以做一个解决方法,扩展TestProbe类并为最后一个 UserInfo 的属性类添加一个默认值。

看看以下,也许它对你有用:

HelloSpec.scala

import org.scalatest._
import scala.concurrent.duration._
import akka.testkit._
import akka.testkit._
import akka.actor._


case class UserInfo(username: String, score: Int, timestamp: String = "")

case class MyTestProbe(_application: ActorSystem) extends TestProbe(_application) {
        def expectApproxMsg(max: Duration = Duration.Undefined, us:UserInfo):UserInfo = {
                val obj = receiveOne(max).asInstanceOf[UserInfo]
                assert(obj ne null, s"timeout ($max) during expectMsg while waiting for $us")
                val expect = us.username == obj.username && us.score == obj.score
                assert(expect, s"expected $us, found $obj")
                obj
        }
}

class HelloSpec extends FlatSpec with Matchers with TestKitBase {
 implicit lazy val system = ActorSystem()
  "TestProbe actor" should "receive correct message" in {

        val probe2 = MyTestProbe(system)
        probe2.ref ! UserInfo("Salc2",9999,"whatever")
        probe2.expectApproxMsg(500 millis, UserInfo("Salc2",9999))

  }
}

测试包源代码

于 2015-12-29T15:57:36.587 回答