我目前正在测试一个akka应用程序。我遇到了一个特定的模式:我想测试TestProbe
是否接收到了特定的消息,对一些字段进行模运算。
例如,如果消息是:
UserInfo(username: String, score: Int, timestamp: String)
然后,我可能想测试username
和score
是否符合预期,但不在乎消息是在什么时候收到的。
目前我想写这样的东西:
testProbe.expectMsgPF() {
case UserInfo(`username`, `score`, _) =>
}
如何扩展测试探针类,以便编写类似的内容?
testProbe.expectApproxMsg(UserInfo(`username`, `score`, _))
除了缩短我的代码外,我希望这个问题的答案能进一步加深我对Scala编程语言的理解。
我认为你不能做这样的
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))
}
}
Testkit 的源代码