Search code examples
scalaakkascalatest

Scala Test, how to take a result from an actor


i have a problem. I'm trying to do some scala tests. My problem is that I don't know how to take the return of a method to test whether it returns a sequence to me or not. How can i do it? My Test class is: (It works)

"The game actor" should {

    "accept a specific numbers of players and notify that the game is started with an initial state" in {
      val gameActor = TestActorRef[GameMatchActor](GameMatchActor.props(NUMBER_OF_PLAYERS))
      val player1 = TestProbe()
      val player2 = TestProbe()

      gameActor ! GamePlayers(Seq(GamePlayer("id1", "player1", player1.ref), GamePlayer("id2", "player2", player2.ref)))
      player1.expectMsgType[MatchFound]
      player1.send(gameActor, PlayerReadyServer("id1", player1.ref))
      player2.expectMsgType[MatchFound]
      player2.send(gameActor, PlayerReadyServer("id2", player2.ref))

      player1.expectMsgType[GamePlayersClient]
      player2.expectMsgType[GamePlayersClient]

    }
  }

And the method that return me GamePlayersClient is:

private def defineRoles(players: Seq[GamePlayer]): Seq[Player] = {
    var playersRole: Seq[Player] = Seq()
    val rand1 = Random.nextInt(players.length)
    val rand2 = Random.nextInt(players.length)

    for (n <- 0 until players.length) {
      n match {
        case n if n == rand1 || n == rand2 =>
          playersRole = playersRole :+ Impostor(players(n).id, players(n).username, Point2D(0,0))
        case _ => playersRole = playersRole :+ Crewmate(players(n).id, players(n).username, Point2D(0,0))
      }
    }
    playersRole
  }

And:

// watch the players with the new actor ref
    val playersRole = defineRoles(players)
    this.players.foreach(p => {
      p.actorRef ! GamePlayersClient(playersRole)
      context.watch(p.actorRef)
    })

So, how can i take GamePlayersClient(playersRole) and search if inside there's a Sequence of Players and one of they is a "Crewmate". Thanks


Solution

  • You can use one of the receive... methods on TestProbe to collect the GamePlayersClient messages sent to the probe and then use ScalaTest's matchers to assert things about those messages.

    For example, you could replace

    player1.expectMsgType[GamePlayersClient]
    

    with

    val gpcMessageOpt1: Option[GamePlayersClient] = Option(player1.receiveN(1)).flatMap {
      case g: GamePlayersClient => Some(g)
      case _ => None
    }
    
    gpcMessageOpt1 shouldNot be(empty) // effectively the same as the expectMessage
    

    If the field of interest is playersRole, then you might have

    // To my mind, it's generally OK to do unsafe things like get in a test...
    gpcMessageOpt1.get.playersRole shouldNot be(empty)