Testing that an actor throws an exception

1,629 views
Skip to first unread message

Carsten Saathoff

unread,
May 9, 2014, 6:56:34 AM5/9/14
to akka...@googlegroups.com
Hi,

I am currently trying to figure out how to best test whether an actor throws an exception. The only solution I can think of is creating that actor as a child of another actor and use the standard supervision to somehow propagate the exception to the test code (probably there are several ways to do it that way). However, that feels somewhat complicated. Is there a more elegant way to test it or support in the Testkit that I am not able to find?

thanks

Carsten

Konrad Malawski

unread,
May 9, 2014, 7:07:53 AM5/9/14
to Akka User List
Nothing like that in TestKit, reason being - you don't usually interact with Actors like that. I think the test should feel more like "when this happens, will it be restarted by it's parent"? etc.
I'd rather structure the test like that, but maybe there's something I'm missing in your use-case.


--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



--
Cheers,
Konrad 'ktoso' Malawski
hAkker - Typesafe, Inc

Carsten Saathoff

unread,
May 9, 2014, 7:26:49 AM5/9/14
to akka...@googlegroups.com
I don't think it's a matter of my use-case,  I think it's a matter of test case granularity. In my system, I throw the Exception because I want the parent to act upon it, so it's part of the actors API. However, I tend to test actors in isolation, i.e., I want to test the child alone and make sure that it acts as expected. When testing the parent, I mock the child where necessary. The reason for that is that I don't want my unit tests to become too complex, which is the case IMO, when testing whole actor hierarchies at once.

But IMHO, when throwing an exception is part of the actors behavior, I think I should be able to test it in isolation, too.

best

Carsten

Konrad 'ktoso' Malawski

unread,
May 9, 2014, 7:34:50 AM5/9/14
to akka...@googlegroups.com, Carsten Saathoff
How about extracting the actor’s behaviour to a trait, and test that trait for the expected throw behaviour using plain old ScalaTest `intercept[Exception] { … }`, would it make sense in your case or are the interactions “very relying on the thing being an actor”?

Having that said, it’s just my personal preference to test like this.
So other options are… 
   a) what you described already, preparing a special parent actor
   b) overriding `aroundReceive(…)` in the tested actor, since it’s “around”, you can have your `intercept[…]` code there. (Feels a bit weird though.)

I hope one of these options fits you! :-)

-- 

Carsten Saathoff

unread,
May 9, 2014, 8:50:43 AM5/9/14
to akka...@googlegroups.com, Carsten Saathoff
Hi,


Am Freitag, 9. Mai 2014 13:34:50 UTC+2 schrieb Konrad Malawski:
How about extracting the actor’s behaviour to a trait, and test that trait for the expected throw behaviour using plain old ScalaTest `intercept[Exception] { … }`, would it make sense in your case or are the interactions “very relying on the thing being an actor”?

right, that's an option I did not think of before. I think that could work.

However, you actually got me thinking about my particular design and whether a thrown Exception should be part of the "API" of an actor at all. Maybe the fact that I can' properly test this is indeed just a consequence of a bad design in that particular case. I assume that's what you meant in your first response with "you usually don't interact with actors in that way"?
 
Thanks so far!

Carsten

Roland Kuhn

unread,
May 9, 2014, 9:32:30 AM5/9/14
to akka-user, Carsten Saathoff
Hi Carsten,

The failure modes of an actor do make sense to view as part of its API, it is something the supervisor will have to know about and prepared to handle (or escalate). Therefore I agree with the sentiment that it should be testable as well. What I use is what I call a StepParent actor that looks like this:

class StepParent(target: ActorRef) extends Actor {
  override val supervisorStrategy = OneForOneStrategy() {
    case thr: Throwable => target ! thr; Restart // or make it configurable/controllable during the test
  }
  def receive = {
    case p: Props => sender ! context.actorOf(p, "child")
  }
}

... // in a test
val parent = system.actorOf(Props(new StepParent(testActor)), "stepParent")
parent ! Props(...) // for the actor under test
val subject = expectMsgType[ActorRef]
// and now test the subject

Regards,

Roland

 
Thanks so far!

Carsten

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Reactive apps on the JVM.
twitter: @rolandkuhn


Carsten Saathoff

unread,
May 10, 2014, 10:11:01 AM5/10/14
to akka...@googlegroups.com, Carsten Saathoff
Hi Roland,


Am Freitag, 9. Mai 2014 15:32:30 UTC+2 schrieb rkuhn:
The failure modes of an actor do make sense to view as part of its API, it is something the supervisor will have to know about and prepared to handle (or escalate). Therefore I agree with the sentiment that it should be testable as well. What I use is what I call a StepParent actor that looks like this:

Yes, after further thinking about it, I also came to the same conclusion.
 
class StepParent(target: ActorRef) extends Actor {
  override val supervisorStrategy = OneForOneStrategy() {
    case thr: Throwable => target ! thr; Restart // or make it configurable/controllable during the test
  }
  def receive = {
    case p: Props => sender ! context.actorOf(p, "child")
  }
}

... // in a test
val parent = system.actorOf(Props(new StepParent(testActor)), "stepParent")
parent ! Props(...) // for the actor under test
val subject = expectMsgType[ActorRef]
// and now test the subject

That's actually very similar to how I tested whether exceptions are thrown. But I also wondered whether it would be possible to make this more convenient. For instance some method on TestActorRef that can be used to check if and what exceptions were thrown. Or are there technical limitations that this is not supported?

best

Carsten

Roland Kuhn

unread,
May 10, 2014, 10:44:13 AM5/10/14
to akka-user, Carsten Saathoff
That is the purpose of `TestActorRef.receive(msg, sender)`, but the restriction is that it covers only message processing which comes directly from the test procedure. In general you should not care which actors are involved and whether your actor under test delegates a task to a temporary child actor: you should only test the externally visible behavior, which means running the actor in its natural habitat. That is what we mean when saying that unit testing is mostly a waste of time: you should concentrate on functional tests. OTOH I would love to redefine “unit testing” to mean “functional testing of a unit” (which conveniently is one actor, including its descendants).

Regards,

Roland


best

Carsten

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Carsten Saathoff

unread,
May 11, 2014, 8:05:44 AM5/11/14
to akka...@googlegroups.com, Carsten Saathoff

Am Samstag, 10. Mai 2014 16:44:13 UTC+2 schrieb rkuhn:
10 maj 2014 kl. 16:11 skrev Carsten Saathoff <car...@kreuzverweis.com>:
That is the purpose of `TestActorRef.receive(msg, sender)`, but the restriction is that it covers only message processing which comes directly from the test procedure. In general you should not care which

The restriction is what restrained me from using it in my specific use case.
 
actors are involved and whether your actor under test delegates a task to a temporary child actor: you should only test the externally visible behavior, which means running the actor in its natural habitat. That is what we mean when saying that unit testing is mostly a waste of time: you should concentrate on functional tests. OTOH I would love to redefine “unit testing” to mean “functional testing of a unit” (which conveniently is one actor, including its descendants).

I agree with you that one should concentrate on functional testing, but nevertheless I have to decide on some separation into functional units that are tested in one piece. And if throwing an exception is part of the externally visible behavior, I still need a tool to test that. And if the exception is not triggered by the message directly received, the TestActorRef.receive() method doesn't help.

Or are you proposing that a functional unit should never throw Exceptions as a part of its external behavior? Or in other words that functional units should always form their own dedicated supervision hierarchy?

best

Carsten
Reply all
Reply to author
Forward
0 new messages