2

I am currently testing an akka application. I have come across a certain pattern: I want to test that a TestProbe has received a certain message, modulo some fields.

For example, if the message was:

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

Then I might want to test the username and score are as expected, but not care at what time the message was received.

Currently I would like write something like this:

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

How could the test probe class be extended so that something like this might be written instead?

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

In addition to shortening my code, I'm hoping an answer to this question will further my understanding of the Scala programming language.

Peter Neyens
  • 9,770
  • 27
  • 33
Mullefa
  • 1,237
  • 1
  • 15
  • 27

1 Answers1

0

I think you can not do something like this

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

Because, first last attribute (timestamp) isn't a var is a val needs to have value and if what you want is passing a pattern by parameter you can't either 'cause we can not pass pattern alone without all case alternatives (PartialFunction).

So UserInfo(username,score, _) is an object, a normal instance.

But we can do a workaround extending TestProbe class and adding a default value to last UserInfo's attribute class.

Look at the following, maybe it works for you:

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))

  }
}

Source code of Testkit

salc2
  • 577
  • 5
  • 14