I've got an actor that will write a file after receiving a certain number of messages.
When compiling, Maven runs all the unit tests we have defined. The problem is that the unit test to check that the file was successfully written to disk happens before the Actor writes the file (which it does correctly).
I've found some documentation for testing Actors, but they're all out of date by several years. How can I wait for a bit before checking that the file exists?
Akka actors are asynchronous from the beginning. Reactive programs can be implemented in either way, synchronous and asynchronous.
Akka actors use java threads internally. More than a few thousand threads running simultaneously produces overhead on most desktop machines. Akka Actors simplifies this problem by providing awake-on-demand actors who do not occupy a thread unless they have some work to do.
What is an Actor in Akka? An actor is essentially nothing more than an object that receives messages and takes actions to handle them. It is decoupled from the source of the message and its only responsibility is to properly recognize the type of message it has received and take action accordingly.
Props is a configuration class which is used to specify options while creating an actor. It is immutable, so it is thread-safe and shareable. You can implement Props by importing akka.
Just to sum up all comments and suggestions:
For synchronous actor testing, use TestProbes (akka.testkit) similar to this:
import org.scalatest.{FunSuite, BeforeAndAfterAll}
import org.scalatest.matchers.ShouldMatchers
import scala.concurrent.duration._
import scala.util.Random
import scala.util.control.NonFatal
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import akka.actor.{ActorSystem, ActorRef, Actor, Props}
import akka.testkit.{TestKit, ImplicitSender, TestProbe}
import scala.concurrent._
import ExecutionContext.Implicits.global
@RunWith(classOf[JUnitRunner])
class Example extends TestKit(ActorSystem("filetest"))
with FunSuite
with BeforeAndAfterAll
with ShouldMatchers
with ImplicitSender
with Tools {
override def afterAll(): Unit = {
system.shutdown()
}
test("Show synchronous actor test") {
val tester = TestProbe()
val fileActor = system.actorOf(Props(classOf[FileActor]), "case2-primary")
tester.send(fileActor, CreateFile(1))
tester.expectMsg(FileCreated(1)) // Will synchronously wait (~500ms in this example)
}
}
case class CreateFile(id: Long)
case class FileCreated(id: Long)
class FileActor extends Actor {
def receive = {
case CreateFile(id) => {
val s = sender
createFile(id).map( id => s ! FileCreated(id))
}
}
def createFile(id: Long): Future[Long] = future {
// "Create" the file...
Thread.sleep(500)
id
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With