Override RootMonitor - scala

I have some code running inside Future.respond, that throws an NPE, because of a bug. The problem is that my unit tests totally missed it, and are all happily passing, because the NPE is swallowed by the RootMonitor.
So, my question is if there is any way to override the RootMonitor behavior for the unit tests to result in a test failure rather than swallowing the exception?
I know, I could just catch the exception inside respond, but that's kinda backwards - if I thought there could be an exception, I would've fixed it in the first place. That's exactly a kind of situation I would like my test to catch.
So, what I am looking for is a way to override the RootMonitor globally for the tests, or else to assert somehow that it handled no exceptions after the test finishes.
Is there a way to do something like this? How do people usually deal with this kind of tests?

Ok, I think, I found a solution. It seems a bit kludgy, so if someone can come up with a better way, please chime in, but here goes.
class MonitoredSuite extends FunSuite {
protected override def withFixture(test: NoArgTest): Outcome = {
var exception: Throwable = null
Monitor.using(Monitor.mk {
case e =>
exception = e
false
})(test()) match {
case x#Exceptional(_) => x
case s if exception == null => s
case _ => Exceptional(exception)
}
}
}
Basically, I install a noop monitor before each test, and then generate a failure if it was invoked.

Related

Unit testing strategy in Scala with Try, Success, Failure

For the sake of simplicity suppose we have a method called listTail which is defined in the following way:
private def listTail(ls: List[Int]): List[Int] = {
ls.tail
}
Also we have a method which handles the exception when the list is empty.
private def handleEmptyList(ls: List[Int]): List[Int] = {
if(ls.isEmpty) List.empty[Int]
}
Now I want to create a safe version of the listTail method, which uses both methods:
import scala.util.{Try, Success, Failure}
def safeListTail(ls: List[Int]): List[Int] = {
val tryTail: Try[List[Int]] = Try(listTail(ls))
tryTail match {
case Success(list) => list
case Failure(_) => handleEmptyList(ls)
}
}
My question is, if the two private methods are already tested, then should I test the safe method as well? And if yes, how?
I was thinking just to check if the pattern matching cases are executed depending on the input. That is, when we hit the Failure case then the handleEmptyList method is executed. But I am now aware of how to check this.
Or do I need to refactor my code, and put everything in a single method? Even though maybe my private methods are much more complex than this in the example.
My test are written using ScalaTest.
Allowing your methods to throw intentionally is a bad idea and definitely isn't in the spirit of FP. It's probably better to capture failure in the type signature of methods which have the ability to fail.
private def listTail(ls: List[Int]): Try[List[Int]] = Try {
ls.tail
}
Now your users know that this will return either an Success or a Failure and there's no magic stack unrolling. This already makes it easier to test that method.
You can also get rid of the pattern matching with a simple def safeTailList(ls: List[Int]) = listTail(l).getOrElse(Nil) with this formulation -- pretty nice!
If you want to test this, you can make it package private and test it accordingly.
The better idea would be to reconsider your algorithm. There's machinery that makes getting the safe tail built-in:
def safeTailList(ls: List[Int]) = ls.drop(1)
It is actually the other way around: normally, you don't want to test private methods, only the public ones, because they are the ones that define your interactions with the outside world, as long as they work as promised, who cares what your private methods do, that's just implementation detail.
So, the bottom line is - just test your safeListTail, and that's it, no need to test the inner implementation separately.
BTW, you don't need the match there: Try(listTail(ls)).getOrElse(handleEmptyList(ls)) is equivalent to what you have there ... which is actually not a very good idea, because it swallows other exceptions, not just the one that is thrown when the list is empty, a better approach would be actually to reinstate match but get rid of Try:
ls match {
case Nil => handleEmptyList(ls)
case _ => listTail(ls)
}

Dealing with errors using idiomatic Scala

I'm writing an HTTPS service for a chat bot and find myself dealing with a lot of Futures and Options. Usually if an Option returns None or a Future fails I want to log the exception and reset the user back to the start. Here's a toy example of how I accomplish this:
(for {
user <- userService.retrieve(userId)
userPet <- Future(user.userPet.get)
_ <- sendTextAsJson(s"You're holding a $userPet!")
} yield {}).recover {
case ex: Exception =>
log.error(ex.toString)
fail
}
This works fine but it feels a little weird to wrap things in Future just so their exceptions are swallowed and dealt with in the recover block. It also feels weird to include an empty yield block. Is there a better way?
What you basically do is using onSuccess or onFailure to retrieve the futures result. What you also might try is Try.
There is an example of the underlying functionality.
http://www.scala-lang.org/api/2.9.3/scala/util/Try.html
I might suggest you this article: http://docs.scala-lang.org/overviews/core/futures.html I can't summarize whats stated there in a few sentences. But if you look to the table of contents on the right side, the point Futures explains what happens and how to handle it is stated under Excepetions. Thats the idiomatic way.
I don't think it's too bad tbh, assuming userService.retrieve() returns a Future in the first place. I'd personnally rather use map in this case to make things a bit more explicit :
val futureMsg = userService.retrieve(userId)
.map(user => sendTextAsJson(s"You're holding a ${user.userPet.get}!")
.recover {
case NonFatal(ex) => //Look it up ;)
log.error(ex.toString)
fail
}
You now have Future[Unit] to do whatever you want with.
I agree with you that that's an awkward use of a for-comprehension. This is how I would write this:
import scala.util.control.NonFatal
userService.retrieve(userId)
.map(_.userPet.get)
.map(userPet => s"You're holding a $userPet!")
.flatMap(sendTextAsJson)
.recover {
case NonFatal(ex) =>
log.error(ex.toString)
fail
}
Looking at your sendTextAsJson and fail functions you seem to want to side-effect when the future completes. I would not use map after you perform the Option.get and instead look at Futures onComplete method to either handle the success of the future or handle the exception throw. I am not sure how this way and recover are different though so double check that. I did like #sascha10000 link to the scala doc futures. Its been a long time since I read that but its a good resource from what I remember
Example implementation of your code with onComplete:
import scala.concurrent.Future
import scala.util.{Failure, Success}
import scala.concurrent.ExecutionContext.Implicits.global
object UserFuture extends App {
def fail = println("failed")
def sendTextAsJson(message: String): Unit = println(message)
case class User(userPet: Option[String])
object userService {
def userPet = Some("dog")
val someUser = User(userPet)
def retrieve(userId: Int): Future[User] = Future {
someUser
}
}
def getPet(userId: Int): Unit = {
userService.retrieve(userId)
.map(user => user.userPet.get)
.onComplete {
case Success(userPet) => sendTextAsJson(s"You're holding a $userPet!")
case Failure(ex) => println(ex.toString); fail
}
}
getPet(1)
Thread.sleep(10000) // I forgot how to use Await. This is just here to be able to make sure we see some printouts in the console.
}

Rethrown exception in overridden method not rethrowing

I'm overriding a method in spray-json in order to catch an exception it throws. In one particular case I want to add special handling, but otherwise I want to rethrow the original exception.
But the exception isn't rethrowing.
object MyObject extends DefaultJsonProtocol {
override def fromField[T](value: JsValue, fieldName: String)(implicit reader: JsonReader[T]) = {
try {
super.fromField(value, fieldName)(reader)
} catch {
case e: DeserializationException =>
if (reader.isInstanceOf[SafeListFormat[_]]) EmptyList.asInstanceOf[T]
else deserializationError("Object is missing required member '" + fieldName + "'", e)
}
}
}
The deserializationError in spray-json: https://github.com/spray/spray-json/blob/master/src/main/scala/spray/json/package.scala
The method I'm overriding is fromField in here: https://github.com/spray/spray-json/blob/master/src/main/scala/spray/json/ProductFormats.scala
In debug mode I can see the original exception being caught, and my else case "rethrowing" the error, and even the deserializationError method being called in spray-json's library. But even through the DeserializationException is a RuntimeException the overridden method doesn't terminate.
I had wondered if there was something about deferred execution of the deserializationError method. But I even tried changing my exception handler from calling deserializationError to a simple throw e and that didnt work either.
What's going on here?
PS. I dont think this is specific to spray-json really, but is probably something interesting I dont know about scala. But I kept the example as a real world as possible just in case it is something particular to the way my overridden method is called by the spray-json library code.
EDIT: Raised same question with spray-user forum: https://groups.google.com/forum/#!topic/spray-user/YXtY6VyIVGk
It seem ok to me to be honest. So here go a few random observations (too long to put as comments):
Call super.fromField[T], right now you are not passing the T param. When things are weird, try to make everything explicit.
You can try functional error handling:
Try(super.fromField(value, fieldName)(reader)).recover {
case e: DeserializationException if (reader.isInstanceOf[SafeListFormat[_]]) => EmptyList.asInstanceOf[T]
case t: Exception => throw t
}.get
Note how I made the if part of the pattern match, doing that might help you insulate the problem.
I find it weird that your method does not terminate. You should probably try reducing the example to something very simple and start adding complexity little by little and see where it breaks.
Best of luck!

Picking the right exception handling in scala

I'm new to Scala, being slightly confused at the various ways to handle exceptions and looking for best-practice advice on the topic. I'm writing a simple method to retrieve a Customer using an existing blocking SDK. The possible outcomes are:
Customer is found
Customer is not found (comes back as a NotFoundException from the SDK)
Error while talking to remote server (SDK throws some other exception)
So I want my method to have a return type Future[Option[Customer]], and return for each case above:
Successful Future: Some(customer)
Successful Future: None
Failed Future
Here is what I wrote using try/catch:
private def findCustomer(userId: Long): Future[Option[Customer]] = future {
try {
Some(gateway.find(userId))
} catch {
case _: NotFoundException => None
}
}
This works fine and seems clean to me, but doesn't seem to be really the "Scala way" to do it - I've been told to avoid using try/catch. So I've been looking for a way to rewrite it using a Try instead.
Here are 2 variants that (I think) behave exactly the same, using a Try.
Variant A:
private def findCustomer(userId: Long): Future[Option[Customer]] = future {
Try(
Some(gateway.find(userId))
).recover {
case _: NotFoundException => None
}.get
}
Variant B:
private def findCustomer(userId: Long): Future[Option[Customer]] = future {
Try(
Some(gateway.find(userId))
).recover {
case _: NotFoundException => None
}
} flatMap {
case Success(s) => Future.successful(s)
case Failure(f) => Future.failed(f)
}
I'm not a huge fan of A (even though it's more concise than B) since the .get seems a bit treacherous. B is definitely the most explicit but mapping the Try cases to corresponding Future outcomes seems boring.
How would an experienced Scala programmer write this?
I think your initial version using try/catch is perfectly fine, because it's a wrapper around an existing SDK.
Alternatively, you can use the recover method on Future:
def findCustomer(userId: Long): Future[Option[Customer]] =
Future(Option(gateway.find(userId))).recover {
case e: NotFoundException => None
}
One option is to avoid chaining Try and Future. In a sense, a future is an asynchronous Try.
You could use Future[Customer] directly and consider NotFoundException as something to recover from rather than a None value. Normally, you would chain operation on the future itself, with no need to deal with the failure cases (by mapping it, etc). It all depends on how you are going to use it (how your logic branches when the future is completed). In other words, maybe it seems convoluted to you because it is, and you are forcing it to be by forcing the Future[Option[Customer]] return type.
The ability to do chain multiple operations and carry on with computing if and only if all if going all right is the nice Scala feature here (especially on for comprehensions, etc).
You might be looking for:
Future.fromTry(myTry)
So for your example you might do:
Future.fromTry {
Try(Some(gateway.find(userId))).recover {
case _: NotFoundException => None
}
}
To only catch the NotFoundException, as in your solution. The only problem here is that the method won't be executed asynchronously. If that is necessary, consider using Future.recover, as suggested by Ionut.
Another idiomatic option worth mentioning here is to use Either[F, S], where S is the type of the successful return, and F can hold the errors (which you might want to propagate). So you could use Either[ Exception, Option[String]] or Either[String, Option[String]] where the first String is an error message.
If you're ready to adopt some scalaz. disjunction from scalaz is very useful and natural in handling erronous scenarios. It's like scala Either but scalaz disjunction \/ is right biased. you'll have success value on the right and exception on left. wrapping your code block with \/.fromTryCatch returns exception on the left side of disjunction. right will always have success value. mapping over disjunction is easiser than Scala Either since disjunction is right biased and easily gives you value from right.
import scalaz.\/
private def findCustomer(userId: Long): Future[\/[Throwable,Option[Customer]] ]= future {
\/.fromTryCatch {
Some(gateway.find(userId))
}
}

Fusing execution flow and exception flow in Scala

I am using the following to wrap a Boolean function and return its success status:
def wrapper(wrapped: => Boolean) : Boolean = { // this form of prototype takes a function by name
try {
return wrapped
} catch {
case anyException : Throwable =>
log(anyException.toString)
return false }
}
The rationale being that the wrapper function should return an overall binary status, regardless of whether the wrapped function failed to capture its own unexpected exceptions and do the same. So the wrapper conveys success and failure via its Boolean return value. It can also be an Option for function result data, rather than a Boolean.
How would you accomplish this in other, even better ways, in Scala?
I note that one rationale (of few others) for this code, admittedly has been that try catch blocks are cumbersome in flow control blocks. Another has been that I tend to use this pattern a lot in a certain area of my project.
You can use Try. Although it will catch only NonFata(scala.util.control.NonFatal) but in most cases this is what you do want.
import scala.util.Try
def wrapper(predicate: => Boolean) : Boolean = {
Try(predicate) getOrElse false
}
Or another way (For example if you really do want to catch any Throwable)
import scala.util.control.Exception._
def wrapper(predicate: => Boolean) : Boolean = {
catching(classOf[Throwable]) opt predicate getOrElse false
}
Scala provides Try feature, which is intended to be used in this occasions.
Notice that keeping your current wrapper leads to potential several errors. When you get a false result, you cannot know if it came from an application exception or a simple false evaluation. Thus, you can't properly handle any exception in your system, which may lead to multiple inconsistencies. Moreover, when you get a false result, your application internal state could be considered as unknown, making it very difficut to look into the box to know if the cat is dead or alive.
To solve this, scala's Try feature will handle this possible states for you, returning -in your case- a Success(elem: Boolean) in case your predicate effectively executes, and a Failure(ex: Throwable) in case an exception was thrown during execution. Then, you can use pattern matching to find out which was the case:
import scala.util.{Try, Success, Failure}
[...]
Try(predicate) match {
case Success(bool) => bool
case Failure(ex) => /* Do something to handle ex */
}
This somehow eliminates the need of your wrapper, for you can keep Try's result and then either match it or get it's result whenever you need to. And, as seen in previous answers, there is a rather complete set of operations you can use to handle all this cases in a more fashionable way.