Testing akka-actors

17

Click here to load reader

description

This presentation is about Testing Akka Actors. We discussed in this presention how to test akka actors using testkit provided by akka framework.

Transcript of Testing akka-actors

Page 1: Testing akka-actors

Testing Akka ActorsTesting Akka Actors

Piyush MishraSoftware Consultant

Knoldus Software LLP

Piyush MishraSoftware Consultant

Knoldus Software LLP

Page 2: Testing akka-actors

Topics CoveredTopics Covered

Basics of Akka

Settings in build.sbt

Defining an of Akka Actor

Creation of Akka Actor

ActorRef

Testing Akka Actors

Integration testing using testkit

Basics of Akka

Settings in build.sbt

Defining an of Akka Actor

Creation of Akka Actor

ActorRef

Testing Akka Actors

Integration testing using testkit

Page 3: Testing akka-actors

What is Akka What is Akka

Akka is framework for writing event driving, concurrent, fault-tolerant and scalable application.

a) It uses actor model to build concurrent, fault-tolerant and scalable application.

b) Actors are the higher abstraction for concurrency and parallelism.

c) They are very lightweight event-driven processes (approximately 2.7 million actors per GB RAM).

d) Akka provides supervisor stategy to build fault toleranceApplications.

Akka is framework for writing event driving, concurrent, fault-tolerant and scalable application.

a) It uses actor model to build concurrent, fault-tolerant and scalable application.

b) Actors are the higher abstraction for concurrency and parallelism.

c) They are very lightweight event-driven processes (approximately 2.7 million actors per GB RAM).

d) Akka provides supervisor stategy to build fault toleranceApplications.

Page 4: Testing akka-actors

Settings in build.sbtSettings in build.sbt

In order to test Akka actors we need to add following two dependencies in build.scala or build.sbt

libraryDependencies ++= Seq( "com.typesafe.akka" % "akka-actor" % "2.0.5", "com.typesafe.akka" % "akka-testkit" % "2.0.5")

In order to test Akka actors we need to add following two dependencies in build.scala or build.sbt

libraryDependencies ++= Seq( "com.typesafe.akka" % "akka-actor" % "2.0.5", "com.typesafe.akka" % "akka-testkit" % "2.0.5")

Page 5: Testing akka-actors

Defining an Akka actorDefining an Akka actorpackage com.Testing

import akka.actor.Actor

class SimpleActor extends Actor {

def receive = { case msg: String => case _ => println("Got other than string") }

}

package com.Testing

import akka.actor.Actor

class SimpleActor extends Actor {

def receive = { case msg: String => case _ => println("Got other than string") }

}

Page 6: Testing akka-actors

Creating an actorCreating an actor

package com.Testing

import akka.actor.ActorSystemimport akka.actor.Props

object CreateActor extends App {

val system = ActorSystem("testing") val actor = system.actorOf(Props[SimpleActor]) actor ! "hello"}

package com.Testing

import akka.actor.ActorSystemimport akka.actor.Props

object CreateActor extends App {

val system = ActorSystem("testing") val actor = system.actorOf(Props[SimpleActor]) actor ! "hello"}

Page 7: Testing akka-actors

What is ActorRefWhat is ActorRef

ActorRef is the Immutable and serializable handle to an actor which may or may not reside on the local host or inside the same ActorSystem .

We can not call methods on actorRef.

ActorRef is the Immutable and serializable handle to an actor which may or may not reside on the local host or inside the same ActorSystem .

We can not call methods on actorRef.

Page 8: Testing akka-actors

Testing with TestActorRefTesting with TestActorRef

This special type of reference is designed specifically for test purposes and allows access to the actor in two ways: either by obtaining a reference to the underlying actor instance, or by invoking or querying the actor's behaviour (receive).

This special type of reference is designed specifically for test purposes and allows access to the actor in two ways: either by obtaining a reference to the underlying actor instance, or by invoking or querying the actor's behaviour (receive).

Page 9: Testing akka-actors

Obtaining a Reference to an Actor Obtaining a Reference to an Actor

import akka.testkit.TestActorRef val actorRef = TestActorRef[MyActor] val actor = actorRef.underlyingActor

import akka.testkit.TestActorRef val actorRef = TestActorRef[MyActor] val actor = actorRef.underlyingActor

Page 10: Testing akka-actors

Testing the Actor's BehaviorTesting the Actor's Behavior

implicit val timeout = Timeout(5 seconds)implicit val system = ActorSystem("Unit")val actorRef = TestActorRef(new SimpleActor)

val result = Await.result((actorRef ? 42), 5 seconds).asInstanceOf[Int] result must be(42)

implicit val timeout = Timeout(5 seconds)implicit val system = ActorSystem("Unit")val actorRef = TestActorRef(new SimpleActor)

val result = Await.result((actorRef ? 42), 5 seconds).asInstanceOf[Int] result must be(42)

Page 11: Testing akka-actors

Integration test with TestkitIntegration test with Testkit

Testkit is used for integration testing of an actor. This toolkit provider a ImplicitSender which is actually a test actor which dispatches messages to actors under test.

Continued

Testkit is used for integration testing of an actor. This toolkit provider a ImplicitSender which is actually a test actor which dispatches messages to actors under test.

Continued

Page 12: Testing akka-actors

Integration test with Testkit Integration test with Testkit class MySpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with WordSpec with MustMatchers with BeforeAndAfterAll {

def this() = this(ActorSystem("MySpec"))

import MySpec._

override def afterAll { system.shutdown() }

"An Echo actor" must {

"send back messages unchanged" in { val echo = system.actorOf(Props[EchoActor]) echo ! "hello world" expectMsg("hello world") }

class MySpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with WordSpec with MustMatchers with BeforeAndAfterAll {

def this() = this(ActorSystem("MySpec"))

import MySpec._

override def afterAll { system.shutdown() }

"An Echo actor" must {

"send back messages unchanged" in { val echo = system.actorOf(Props[EchoActor]) echo ! "hello world" expectMsg("hello world") }

Page 13: Testing akka-actors

Timing AssertionsTiming Assertions

Timing: certain events must not happen immediately (like a timer), others need to happen before a deadline.

The block given to within must complete after a Duration which is between min and max, where the former defaults to zero. The deadline calculated by adding the max parameter to the block's start time is implicitly available within the block to all examination methods

Timing: certain events must not happen immediately (like a timer), others need to happen before a deadline.

The block given to within must complete after a Duration which is between min and max, where the former defaults to zero. The deadline calculated by adding the max parameter to the block's start time is implicitly available within the block to all examination methods

Page 14: Testing akka-actors

Timing AssertionsTiming Assertionsclass Timing(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with MustMatchers with WordSpec { def this() = this(ActorSystem("MySpec"))

import MySpec._

"An simple actor" must {

"send reply within 2 seconds" in { val worker = system.actorOf(Props[SimpleActor]) within(200 millis) { worker ! 4 expectMsg(4) expectNoMsg // will block for the rest of the 200ms Thread.sleep(300) // will NOT make this block fail } } }}

class Timing(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with MustMatchers with WordSpec { def this() = this(ActorSystem("MySpec"))

import MySpec._

"An simple actor" must {

"send reply within 2 seconds" in { val worker = system.actorOf(Props[SimpleActor]) within(200 millis) { worker ! 4 expectMsg(4) expectNoMsg // will block for the rest of the 200ms Thread.sleep(300) // will NOT make this block fail } } }}

Page 15: Testing akka-actors

Using ProbesUsing Probes

When the actors under test are supposed to send various messages to different destinations. approach is to use it for creation of simple probe actors to be inserted in the message flows. To make this more powerful and convenient, there is a concrete implementation called TestProbe.

The functionality is best explained using a small example

When the actors under test are supposed to send various messages to different destinations. approach is to use it for creation of simple probe actors to be inserted in the message flows. To make this more powerful and convenient, there is a concrete implementation called TestProbe.

The functionality is best explained using a small example

Page 16: Testing akka-actors

Using ProbesUsing Probesclass Probe(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with WordSpec with MustMatchers with BeforeAndAfterAll {

def this() = this(ActorSystem("MySpec"))

import MySpec._

override def afterAll { system.shutdown() }

"An DoubleEcho actor" must {

"send reply both probes" in { val probe1 = TestProbe() val probe2 = TestProbe() val actor = system.actorOf(Props[MyDoubleEcho]) actor ! (probe1.ref, probe2.ref) actor ! "hello" probe1.expectMsg(500 millis, "hello") probe2.expectMsg(500 millis, "hello") } }}

class Probe(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with WordSpec with MustMatchers with BeforeAndAfterAll {

def this() = this(ActorSystem("MySpec"))

import MySpec._

override def afterAll { system.shutdown() }

"An DoubleEcho actor" must {

"send reply both probes" in { val probe1 = TestProbe() val probe2 = TestProbe() val actor = system.actorOf(Props[MyDoubleEcho]) actor ! (probe1.ref, probe2.ref) actor ! "hello" probe1.expectMsg(500 millis, "hello") probe2.expectMsg(500 millis, "hello") } }}

Page 17: Testing akka-actors

ThanksThanks