Gleeb
Gleeb

Reputation: 11289

How to test for an Async side effect with Scala and Mockito

I have a simple scenario where I do some work on 3rd party services and if there was a failure in one of them, then I want to clean up what was done.

The client does not need to wait for the cleanup to complete to get a response so the cleanup is done as a side affect, async function.

While using Mockito I want to verify that the cleanup method was called, but I am getting a race condition and a non deterministic test.

Here is the code snippet:

val eventualImage = imageService.saveImage(uploadedImage, None, parent, imageActions)
ScalaFutures.whenReady(eventualImage.failed, timeout(6 seconds), interval(15 millis)) { ex =>
  val x = Mockito.verify(mockS3Repository, Mockito.times(1)).deleteFileFromS3(s3Location) // where this function is pure async and nothing is waiting for her to complete
  ex shouldBe a [exception.type]
}

Is there any way I can wait for it to complete with out changing my code?

Upvotes: 2

Views: 2167

Answers (2)

Gleeb
Gleeb

Reputation: 11289

As @Lodewijk Bogaards suggested in his comment. using the eventually block solved my problem.

here is an example:

First add the with Eventually to your class declaration

And then the code from the question will be completed like so:

      val eventualImage = imageService.saveImage(uploadedImage, None, parent, imageActions)
      ScalaFutures.whenReady(eventualImage.failed, timeout(6 seconds), interval(15 millis)) { ex =>
        ex shouldBe a [exception.type]
        eventually(timeout(6 seconds), interval(15 millis)){
          Mockito.verify(mockS3Repository, Mockito.times(1)).deleteFileFromS3(s3Location)
        }
      }

Upvotes: 3

Jeff Bowman
Jeff Bowman

Reputation: 95664

You can do timeout-based verification by calling the timeout method.

Mockito.verify(mockS3Repository, Mockito.timeout(5000)).deleteFileFromS3(s3Location)

Though you shouldn't need times(1), as it's the default behavior, you can chain the two together by calling timeout(5000).times(1) and so forth.

Upvotes: 2

Related Questions