How to test for a failed Future

8,380 views
Skip to first unread message

Drew Kutcharian

unread,
Jan 23, 2014, 7:46:23 PM1/23/14
to scalate...@googlegroups.com
Hey Guys,

I have a method insert(user: User): Future[Unit] that returns a failed Future with an Exception when the user already exists in the database. How can I test to make sure the Exception is thrown or more specifically the method returns a failed Future?

Cheers,

Drew

Bill Venners

unread,
Jan 23, 2014, 7:55:17 PM1/23/14
to scalate...@googlegroups.com
Hi Drew,


On Thu, Jan 23, 2014 at 4:46 PM, Drew Kutcharian <dr...@venarc.com> wrote:
Hey Guys,

I have a method insert(user: User): Future[Unit] that returns a failed Future with an Exception when the user already exists in the database. How can I test to make sure the Exception is thrown or more specifically the method returns a failed Future?

The syntax is described in its supertype, Futures:

http://doc.scalatest.org/2.0/index.html#org.scalatest.concurrent.Futures

Something like:

whenReady(result.failed) { ex =>
  ex shouldBe an [ExpectedException]
}

Where ExpectedException is whatever type of exception you are expecting. If you want to inspect the exception further, you could, for example, use this syntax:

ex should have message "bla"


Bill
 
Cheers,

Drew

--
You received this message because you are subscribed to the Google
Groups "scalatest-users" group.
To post to this group, send email to scalate...@googlegroups.com
To unsubscribe from this group, send email to
scalatest-use...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/scalatest-users?hl=en
ScalaTest itself, and documentation, is available here:
http://www.artima.com/scalatest
---
You received this message because you are subscribed to the Google Groups "scalatest-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalatest-use...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Bill Venners
Artima, Inc.
http://www.artima.com

Drew Kutcharian

unread,
Jan 23, 2014, 8:10:25 PM1/23/14
to scalate...@googlegroups.com
Thanks Bill, I’ve been using whenReady but didn’t know I could do this with it too.

- Drew

Bill Venners

unread,
Jan 23, 2014, 11:44:38 PM1/23/14
to scalate...@googlegroups.com
Hi Drew,

I'm not sure it occurred to me either until you asked, though perhaps it did long ago and since forgot. Regardless I think I should add such an example to the documentation.

Bill

Ryan O'Rourke

unread,
Jan 30, 2014, 7:08:20 PM1/30/14
to scalate...@googlegroups.com
Hi Bill,

We just recently upgraded to ScalaTest 2.0 and I'm loving all the improvements.

That said, when I first started looking at FutureConcept/ScalaFutures I was a little disappointed.  For one thing there didn't seem to be a way to test for failed futures - I didn't think of using the failed projection, that is clever.  Please do add it to the documentation!

I was also disappointed because I had rolled my own "FutureResults" trait that looked a little different and I'm more used to that style.  I tried to copy the style of OptionValues, where you can sort of extract the result of the Future inline when writing your assertions.  They work with pimps and implicit conversions (much like OptionValues).  For example,

   val myFuture = Future.successful(7)
   myFuture.success should equal(7)

   val expectedException = new RuntimeException
   val myFailure = Future.failure(expectedException)
   myFailure.failure should equal(expectedException) // or
   evaluating (myFailure.throwFailure) should produce[RuntimeException]

I also made some BeMatchers if all you want to do is verify that a future succeeds or fails and don't care about its value.  This is particularly useful when dealing with unit futures:

     val myUnitFuture: Future[Unit] = ...
   myUnitFuture should be(success)

If I understand how to use ScalaFutures correctly the equivalent would be:

     whenReady(myUnitFuture) { s => s should be(()) }

or maybe just an empty body for whenReady?  Either way I think the BeMatcher version reads better.

Also, in all of these cases I have pretty nice descriptive failure messages, e.g. for myFailure.failure if you actually get a success, the failure message is something like "Expected future failure, but got success with value: XXX".  Using ScalaFutures with the failed projection I got "The future returned an exception of type: java.util.NoSuchElementException, with message: Future.failed not completed with a throwable.."

Anyhow, I am very glad to see the Future support in ScalaTest, which does definitely have some big improvements over my own handrolled stuff - I was using Await rather than polling, for one thing.  And I'm sure that I'll get used to the different style. Sorry I did not look at what was coming sooner - I would have definitely suggested the BeMatchers, at least. 

Thanks,
Ryan

Bill Venners

unread,
Jan 30, 2014, 9:31:40 PM1/30/14
to scalate...@googlegroups.com
Hi Ryan,

There's a bit of lowest common denominator going on in ScalaTest's syntax for futures, because org.scalatest.Futures was also intended to be useful for other kinds of futures besides Scala ones, the old, deprecated Scala future, Java futures, Twitter futures, etc.

That said, similar to your:

myFuture.success should equal(7)

You can currently write:

myFuture.futureValue should equal(7)

And for your:

myFailure.failure should equal(expectedException)

You can currently write::

myFailure.failed.futureValue should equal(expectedException)

It might be nice to be able to assert for Scala futures (or any future that has a succeed/fail notion):

myFuture.successValue should equal(7)
myFailure.failureValue should equal(expectedException)

And I think I also like:

myUnitFuture should be a success
myUnitFuture should be a failure

That syntax also would make sense for a Try, and also a scalaz Validation, so seems like it would make sense to enable this with a typeclass. I'll look at doing something like this in a future release (not 2.1, which is baked except for one enhancement.) The trick will be to just enable it for futures that have the notion of succeed/fail, but that sounds like yet another typeclass enabler.

Thanks for your suggestions.

Bill

Ryan O'Rourke

unread,
Jan 31, 2014, 11:40:46 AM1/31/14
to scalate...@googlegroups.com
Bill,

Sounds good - I definitely agree similar handling would be useful for Try, et al.  And thanks for pointing out how you can use "futureValue" and "futureValue.failed".

Matthew Pease

unread,
Feb 3, 2014, 7:43:26 AM2/3/14
to scalate...@googlegroups.com
Hi guys -

  I'm having issues with 

whenReady(someFuture) {
  verifyCode
}

   Sometimes the verifyCode works, other times it does not work.  I'm handling a successful future whereby I use a mock to return a successful future.  I pass my mock w/ future generating method to my Class Under Test.    I call a method on my CUT and then use the whenReady to check for the outcome of the test.

   I've tracked the non-deterministic behavior down to when my CUT code calls out to another mocked method.  This is a method with no return type & I didn't provide a mocked implementation of that method.  

   The end result is that sometimes the verifyCode works, other times it does not work.   Sometimes my CUT code runs?  And other times it doesn't?

   How well tested is all this Mockito / scalatest / futures sort of code?

Thank you-
Matt
Reply all
Reply to author
Forward
0 new messages