How to test methods that return Future? - scala

I'd like to test a method that returns a Future. My attempts were as follows:
import org.specs2.mutable.Specification
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
class AsyncWebClientSpec extends Specification{
"WebClient when downloading images" should {
"for a valid link return non-zero content " in {
val testImage = AsyncWebClient.get("https://www.google.cz/images/srpr/logo11ww.png")
testImage.onComplete { res =>
res match {
case Success(image) => image must not have length(0)
case _ =>
}
AsyncWebClient.shutDown
}
}
}
}
Apart from the fact that I am unable to make this code work I guess that there could be a better way of testing a futures with a Future-oriented matcher.
How to do it properly in specs2?

You can use the Matcher.await method to transform a Matcher[T] into a Matcher[Future[T]]:
val testImage: Future[String] =
AsyncWebClient.get("https://www.google.cz/images/srpr/logo11ww.png")
// you must specify size[String] here to help type inference
testImage must not have size[String](0).await
// you can also specify a number of retries and duration between retries
testImage must not have size[String](0).await(retries = 2, timeout = 2.seconds)
// you might also want to check exceptions in case of a failure
testImage must throwAn[Exception].await

Took me awhile to find this so thought I'd share. I should've read the release notes. In specs2 v3.5, it is required to use implicit ExecutionEnv to use await for future. This can also be used for future transformation (i.e. map) see http://notes.implicit.ly/post/116619383574/specs2-3-5.
excerpt from there for quick reference:
import org.specs2.concurrent.ExecutionEnv
class MySpec extends mutable.Specification {
"test of a Scala Future" >> { implicit ee: ExecutionEnv =>
Future(1) must be_>(0).await
}
}

Await is an anti pattern. Shouldn't ever use it.
You can use traits like ScalaFutures, IntegrationPatience, and Eventually.
whenReady does the magic you are looking for.
Example:
import org.specs2.mutable.Specification
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success}
import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures}
import scala.concurrent.Future
class AsyncWebClientSpec extends Specification
with ScalaFutures
with IntegrationPatience {
"WebClient when downloading images" should {
"for a valid link return non-zero content " in {
whenReady(Future.successful("Done")){ testImage =>
testImage must be equalTo "Done"
// Do whatever you need
}
}
}
}

There is a nice thing for that in specs2 - implicit await method for Future[Result]. If you take advantage of future transformations you can write like this:
"save notification" in {
notificationDao.saveNotification(notification) map { writeResult =>
writeResult.ok must be equalTo (true)
} await
}
Future composition comes to the rescue when some data arrangement with async functions is needed:
"get user notifications" in {
{
for {
_ <- notificationDao.saveNotifications(user1Notifications)
_ <- notificationDao.saveNotifications(user2Notifications)
foundUser1Notifications <- notificationDao.getNotifications(user1)
} yield {
foundUser1Notifications must be equalTo (user1Notifications)
}
} await
}
Note how we have to use an additional block around for-comprehension to convince compiler. I think it's noisy, so if we turn await method in a function we come up with a nicer syntax:
def awaiting[T]: Future[MatchResult[T]] => Result = { _.await }
"get user notifications" in awaiting {
for {
_ <- notificationDao.saveNotifications(user1Notifications)
_ <- notificationDao.saveNotifications(user2Notifications)
foundUser1Notifications <- notificationDao.getNotifications(user1)
} yield {
foundUser1Notifications must be equalTo (user1Notifications)
}
}

Wondering why #etorreborre did not mention "eventually"
See https://github.com/etorreborre/specs2/blob/master/tests/src/test/scala/org/specs2/matcher/EventuallyMatchersSpec.scala#L10-L43
class EventuallyMatchersSpec extends Specification with FutureMatchers with ExpectationsDescription { section("travis")
addParagraph { """
`eventually` can be used to retry any matcher until a maximum number of times is reached
or until it succeeds.
""" }
"A matcher can match right away with eventually" in {
1 must eventually(be_==(1))
}
"A matcher can match right away with eventually, even if negated" in {
"1" must not (beNull.eventually)
}
"A matcher will be retried automatically until it matches" in {
val iterator = List(1, 2, 3).iterator
iterator.next must be_==(3).eventually
}
"A matcher can work with eventually and be_== but a type annotation is necessary or a be_=== matcher" in {
val option: Option[Int] = Some(3)
option must be_==(Some(3)).eventually
}

onComplete returns Unit, so that block of code returns immediately and the test ends before being able to do anything. In order to properly test the result of a Future, you need to block until it completes. You can do so using Await, and setting a maximum Duration to wait.
import scala.concurrent._
import scala.concurrent.duration._
Await.result(testImage, Duration("10 seconds")) must not have length(0)

Related

How to set a timeout for Async suite in Scalatest?

Consider the following unit test example:
class MySpec extends AsyncFlatSpec {
"this" should "fail after some timeout" in {
val resultFuture: Future[_] = Promise().future
for (result <- resultFuture) yield {
assert(result == ???) // some assertions
assert(result == ???) // some assertions
assert(result == ???) // some assertions
}
}
}
The problem
If resultFuture never completes the test suite never finishes either.
As I understand it's due to the way how SerialExecutionContext is implemented.
The question
Is there any "nice" way how to setup a timeout for this kind of tests, so that if the future isn't complete the test just fails, instead of blocking the entire test suite for eternity?
UPDATE and clarification
While solutions https://stackoverflow.com/a/65746143/96766 and https://stackoverflow.com/a/65749840/96766 (posted by #matthias-berndt and #tomer-shetah) work for the case of blocked thread, it's not exactly what I'm looking for.
Let me make an important clarification to the question. In my case the future isn't eventually complete, but never complete. For example, when a Future is obtained from the Promise that is never resolved (nobody calls success nor failure on it). In that case the proposed solutions still block infinitely.
Is there a way to work this around for AsyncSpec without resorting to using a real pool-based execution context and Await-ing on the future?
Use eventually from scalatest
extends Eventually
Use the following code to set up timeout and interval for checking
import scala.concurrent.duration._
eventually(timeout(1 minutes), interval(5 seconds)) {
resultFuture.futureValue shouldBe ???
}
Use the AsyncTimeLimitedTests trait.
https://www.scalatest.org/scaladoc/3.2.0/org/scalatest/concurrent/AsyncTimeLimitedTests.html
You can use the trait TimeLimits. For example, you can have a test class:
class MySpec extends AsyncFlatSpec with TimeLimits {
"this" should "fail" in {
failAfter(2.seconds) {
val resultFuture: Future[_] = Future {
Thread.sleep(3000)
}
assert(true)
}
}
"this" should "pass" in {
failAfter(2.seconds) {
val resultFuture: Future[_] = Future {
Thread.sleep(1000)
}
assert(true)
}
}
}

Eagerly-evaluate-and-forget behavior for Cats Effect IO

I'm converting Future code to IO. I have code similar to this
def doSomething: Future[Foo] = {
Future {
//some code the result of which we don't care about
}
Future {
//Foo
}
}
And then at the end of the program, I doSomething.unsafeRunSync. How do I convert these Futures to IOs while maintaining the fire-and-forget functionality of the first Future? In using IO's async API, I am worried about accidentally blocking the thread when I later call unsafeRunSync on doSomething.
A solution that uses only cats-effect could use IO.start. This, combined with the fact that you will then never join the resulting Fiber, will look something like this:
import cats.effect._
import cats.implicits._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object ExampleApp extends App{
val fireAndForget =
IO(println("Side effect pre-sleep")) *>
IO.sleep(2.seconds) *>
IO(println("Side effect post-sleep"))
val toBeUsed = IO{
println("Inside second one")
42
}
val result = for {
fiber <- IO.shift *> fireAndForget.start
res <- toBeUsed.handleErrorWith { error =>
// This is just in case you 'toBeUsed' can actually fail,
// and you might want to cancel the original side-effecting IO
fiber.cancel *> IO.raiseError(error) }
} yield res
println(result.unsafeRunSync())
println("Waiting 3 seconds...")
IO.sleep(3.seconds).unsafeRunSync()
println("Done")
}
This will print (most of the times) something similar to:
Side effect pre-sleep
Inside second one
42 // Up until here, will be printed right away
Waiting 3 seconds... // It will then be waiting a while
Side effect post-sleep // ...at which point the side effecting code terminates
Done
Finally, here are more details about Fiber and IO.shift
I believe that you need to wrap the first Future in such a way that it completes immediately. We ignore exeptions, or catch them however, but they are contained within its own thread. The parameter cb is the promise that needs to complete; so we short-circuit the completion by providing a value immediately.
def firstFuture(implicit ec: ExecutionContext): IO[Unit] = {
IO.async[Unit] { cb =>
ec.execute(() => {
try {
//some code the result of which we don't care about
} catch {
}
})
cb(Right(()))
}
}
In the for-comprehension, the firstFuture will complete immediately even though its thread will have a long-running task active on it.
def doSomething(implicit ec: ExecutionContext): IO[Foo] = {
for {
_ <- firstFuture
IO.async[Foo] { fb =>
// Foo
}
}
}

Get actual value in Future Scala [duplicate]

I am a newbie to scala futures and I have a doubt regarding the return value of scala futures.
So, generally syntax for a scala future is
def downloadPage(url: URL) = Future[List[Int]] {
}
I want to know how to access the List[Int] from some other method which calls this method.
In other words,
val result = downloadPage("localhost")
then what should be the approach to get List[Int] out of the future ?
I have tried using map method but not able to do this successfully.`
The case of Success(listInt) => I want to return the listInt and I am not able to figure out how to do that.
The best practice is that you don't return the value. Instead you just pass the future (or a version transformed with map, flatMap, etc.) to everyone who needs this value and they can add their own onComplete.
If you really need to return it (e.g. when implementing a legacy method), then the only thing you can do is to block (e.g. with Await.result) and you need to decide how long to await.
You need to wait for the future to complete to get the result given some timespan, here's something that would work:
import scala.concurrent.duration._
def downloadPage(url: URL) = Future[List[Int]] {
List(1,2,3)
}
val result = downloadPage("localhost")
val myListInt = result.result(10 seconds)
Ideally, if you're using a Future, you don't want to block the executing thread, so you would move your logic that deals with the result of your Future into the onComplete method, something like this:
result.onComplete({
case Success(listInt) => {
//Do something with my list
}
case Failure(exception) => {
//Do something with my error
}
})
I hope you already solved this since it was asked in 2013 but maybe my answer can help someone else:
If you are using Play Framework, it support async Actions (actually all Actions are async inside). An easy way to create an async Action is using Action.async(). You need to provide a Future[Result]to this function.
Now you can just make transformations from your Future[List[Int]] to Future[Result] using Scala's map, flatMap, for-comprehension or async/await. Here an example from Play Framework documentation.
import play.api.libs.concurrent.Execution.Implicits.defaultContext
def index = Action.async {
val futureInt = scala.concurrent.Future { intensiveComputation() }
futureInt.map(i => Ok("Got result: " + i))
}
You can do something like that. If The wait time that is given in Await.result method is less than it takes the awaitable to execute, you will have a TimeoutException, and you need to handle the error (or any other error).
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{Try, Success, Failure}
import scala.concurrent.duration._
object MyObject {
def main(args: Array[String]) {
val myVal: Future[String] = Future { silly() }
// values less than 5 seconds will go to
// Failure case, because silly() will not be done yet
Try(Await.result(myVal, 10 seconds)) match {
case Success(extractedVal) => { println("Success Happened: " + extractedVal) }
case Failure(_) => { println("Failure Happened") }
case _ => { println("Very Strange") }
}
}
def silly(): String = {
Thread.sleep(5000)
"Hello from silly"
}
}
The best way I’ve found to think of a Future is a box that will, at some point, contain the thing that you want. The key thing with a Future is that you never open the box. Trying to force open the box will lead you to blocking and grief. Instead, you put the Future in another, larger box, typically using the map method.
Here’s an example of a Future that contains a String. When the Future completes, then Console.println is called:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Main {
def main(args:Array[String]) : Unit = {
val stringFuture: Future[String] = Future.successful("hello world!")
stringFuture.map {
someString =>
// if you use .foreach you avoid creating an extra Future, but we are proving
// the concept here...
Console.println(someString)
}
}
}
Note that in this case, we’re calling the main method and then… finishing. The string’s Future, provided by the global ExecutionContext, does the work of calling Console.println. This is great, because when we give up control over when someString is going to be there and when Console.println is going to be called, we let the system manage itself. In constrast, look what happens when we try to force the box open:
val stringFuture: Future[String] = Future.successful("hello world!")
val someString = Future.await(stringFuture)
In this case, we have to wait — keep a thread twiddling its thumbs — until we get someString back. We’ve opened the box, but we’ve had to commandeer the system’s resources to get at it.
It wasn't yet mentioned, so I want to emphasize the point of using Future with for-comprehension and the difference of sequential and parallel execution.
For example, for sequential execution:
object FuturesSequential extends App {
def job(n: Int) = Future {
Thread.sleep(1000)
println(s"Job $n")
}
val f = for {
f1 <- job(1)
f2 <- job(2)
f3 <- job(3)
f4 <- job(4)
f5 <- job(5)
} yield List(f1, f2, f3, f4, f5)
f.map(res => println(s"Done. ${res.size} jobs run"))
Thread.sleep(6000) // We need to prevent main thread from quitting too early
}
And for parallel execution (note that the Future are before the for-comprehension):
object FuturesParallel extends App {
def job(n: Int) = Future {
Thread.sleep(1000)
println(s"Job $n")
}
val j1 = job(1)
val j2 = job(2)
val j3 = job(3)
val j4 = job(4)
val j5 = job(5)
val f = for {
f1 <- j1
f2 <- j2
f3 <- j3
f4 <- j4
f5 <- j5
} yield List(f1, f2, f3, f4, f5)
f.map(res => println(s"Done. ${res.size} jobs run"))
Thread.sleep(6000) // We need to prevent main thread from quitting too early
}

How do I test scala.js programs for side-effects that happen asynchronously using µtest?

I have a µtest suite that needs to check that some asynchronous operation eventually has a side effect. Since javascript (and thus scala.js) is single threadded, it is not possible to block and wait for the side effect to happen. Also, the µtest eventually method does not work on javascript runtime. How do I perform such a test?
If you return a Future from a µtest, then the test will pass if the future succeeds and fail if the future fails. Thus, you can schedule the conditional check for some point in the future without blocking.
I wrote a simple eventually method that accomplishes this:
package utest
import rx.ops.DomScheduler
import scala.concurrent.{Promise, Future}
import scala.concurrent.duration.FiniteDuration
import scala.util.{Failure, Success, Try}
object JsOps {
import scala.concurrent.ExecutionContext.Implicits.global
val scheduler = new DomScheduler
def eventually(eval: => Try[Boolean])(implicit timeout: FiniteDuration): Future[Boolean] = {
val p = Promise[Boolean]()
scheduler.scheduleOnce(timeout) {
eval match {
case Success(b) => p.success(b)
case Failure(t) => p.failure(t)
}
}
p.future
}
}
Here is an example of usage:
import scala.concurrent.duration._
implicit val timeout = 30.milliseconds
eventually {
if (/*condition holds true*/) {
Success(true)
} else Failure(new RuntimeException(/*error message*/))
}

How to use "eventually" with "Specs2RouteTest"

There are two specs here. First is not passing because eventually in check will not cause whole route rerun but this is the way I would prefer to follow. The second spec is the best solution I found (and prove that it is doable ;) ) but it contains some boilerplate like additional function which in real life will have to return rather tuple than single thing and it is inconsistent with spray-tests syntax design to test routs.
So question is:
How to use eventually with spray-tests to be as close as possible to syntax from first spec.
import org.specs2.mutable.Specification
import spray.routing.Directives
import spray.http._
import MediaTypes._
import HttpCharsets._
import spray.testkit.Specs2RouteTest
class EventuallyAndRouts extends Specification with Directives with Specs2RouteTest {
var i = 0
def incAndGet = {
i = i + 1
println(s"This is i = $i")
s"$i"
}
"The testing infrastructure should support an eventually matcher" >> {
"but it is not working inside a check as I need :( (and this will fail)" in {
i = 0
Get() ~> complete(incAndGet) ~> check {
body must eventually(7, 20 millis)(be_===(HttpEntity(ContentType(`text/plain`, `UTF-8`), "5")))
}
}
"so I got workaround :/ (and this is passing)" in {
i = 0
def requestResult = Get() ~> complete(incAndGet) ~> check {
body
}
requestResult must eventually(7, 20 millis)(be_===(HttpEntity(ContentType(`text/plain`, `UTF-8`), "5")))
}
}
}
eventually is used to evaluate repeatedly a value that is changing. So it either has to be a var, a def or a byname parameter.
The best way around that is probably for you to implement a checkEventually(times, delay) method that will incorporate the eventually call. Something like that:
implicit class Checked(request: =>Request) {
def checkEventually[R : AsResult](times: Int, delay: Duration, matcher: Matcher[RequestResult])(body: =>Unit)( = {
val requestResult = result ~> check(body)
requestResult must eventually(times, delay)(matcher)
}
}