Scala Mockito Verify method is always Successful - scala

I am trying to use verify method of mockito using scala as a language. However for my case verify method is always successful, even if that method is not being called.
Below is the codeline where getDetailsBySkus calls method getPriceAndAvailability just once internally. How can I make this work ?
Below is the code snippet.
Code:
doReturn(Future(TestConstantsSpec.PNA_RESPONSE), Nil: _*)
.when(distributorService).getPriceAndAvailability(ArgumentMatchers.any())(ArgumentMatchers.any())
"empty part number" should "not execute calls-1" in {
purchaseOrderService.getDetailsBySkus(purchaseOrder.distributor, Seq("KJH"))
.flatMap(output => {
verify(distributorService, Mockito.atLeast(10))
.getPriceAndAvailability(ArgumentMatchers.any())(ArgumentMatchers.any()) // successful
Future(output)
}
)
}
"empty part number" should "not execute calls-2" in {
purchaseOrderService.getDetailsBySkus(purchaseOrder.distributor, Seq("KJH"))
.flatMap(output => {
verify(distributorService, Mockito.atLeast(100))
.getPriceAndAvailability(ArgumentMatchers.any())(ArgumentMatchers.any()) // successful
Future(output)
}
)
}

Your test cases are not waiting for the completion of the Futures, if you are using ScalaTest or similar, here's where you can read up on your options: https://www.scalatest.org/user_guide/async_testing

Related

How to make an expect statement be condition for if statement

I'm currently finding the current url with
expect(browser.getCurrentUrl()).toEqual("example.com");
I want to make it into an if statement that would the url as the condition. How could I do that?
if(browser.driver.getCurrentUrl().toEqual("example.com") == "example.com"){
//do stuff
}
This is what I tried and it did not work
getCurrentUrl() is a promise, so you need to resolve it yourself to use the value as a conditional.
browser.getCurrentUrl().then((url) => {
if(~url.indexOf('example.com')) {
// code
}
else {
// code
}
})
Finally, Jasmine methods like toEqual should be used strictly with test assertions. I wouldn't use them outside of an expect statement like you have above.

Returning value from Scala future completion

Coming from a Java background, I have been trying to teach myself Scala for some time now. As part of that, I am doing a small pet project that exposes a HTTP endpoint that saves the registration numberof a vehicle against the owner and returns the status.
To give more context, I am using Slick as FRM which performs DB operations asynchronously and returns a Future.
Based on the output of this Future, I want to set the status variable to return back to the client.
Here, is the code
def addVehicleOwner(vehicle: Vehicle): String = {
var status = ""
val addFuture = db.run((vehicles returning vehicles.map(_.id)) += vehicle)
addFuture onComplete {
case Success(id) => {
BotLogger.info(LOGTAG, s"Vehicle registered at $id ")
status = String.format("Registration number - '%s' mapped to owner '%s' successfully", vehicle.registration,
vehicle.owner)
println(s"status inside success $status") //--------- (1)
}
case Failure(e: SQLException) if e.getMessage.contains("SQLITE_CONSTRAINT") => {
status = updateVehicleOwner(vehicle)
BotLogger.info(LOGTAG, s"Updated owner='${vehicle.owner}' for '${vehicle.registration}'")
}
case Failure(e) => {
BotLogger.error(LOGTAG, e)
status = "Sorry, unable to add now!"
}
}
exec(addFuture)
println(s"Status=$status") //--------- (2)
status
}
// Helper method for running a query in this example file:
def exec[T](sqlFuture: Future[T]):T = Await.result(sqlFuture, 1 seconds)
This was fairly simple in Java. With Scala, I am facing the following problems:
The expected value gets printed at (1), but (2) always prints empty string and same is what method returns. Can someone explain why?
I even tried marking the var status as #volatile var status, it still evaluates to empty string.
I know, that the above is not the functional way of doing things as I am muting state. What is the clean way of writing code for such cases.
Almost all the examples I could find described how to map the result of Success or handle Failure by doing a println. I want to do more than that.
What are some good references of small projects that I can refer to? Specially, that follow TDD.
Instead of relying on status to complete inside the closure, you can recover over the Future[T] which handle the exception if they occur, and always returns the result you want. This is taking advantage of the nature of expressions in Scala:
val addFuture =
db.run((vehicles returning vehicles.map(_.id)) += vehicle)
.recover {
case e: SQLException if e.getMessage.contains("SQLITE_CONSTRAINT") => {
val status = updateVehicleOwner(vehicle)
BotLogger.info(
LOGTAG,
s"Updated owner='${vehicle.owner}' for '${vehicle.registration}'"
)
status
}
case e => {
BotLogger.error(LOGTAG, e)
val status = "Sorry, unable to add now!"
status
}
}
val result: String = exec(addFuture)
println(s"Status = $result")
result
Note that Await.result should not be used in any production environment as it synchronously blocks on the Future, which is exactly the opposite of what you actually want. If you're already using a Future to delegate work, you want it to complete asynchronously. I'm assuming your exec method was simply for testing purposes.

Spray route rejections

I am building some custom directives with Spray and I find a problem:
When a route is rejected I thought that it was immediately completed with a rejection. However it is not and it tries to complete the inner route. For example, in this code:
path("users") {
post {
entity(as[User]){
user =>
directive_always_reject(){
println("Hello")
complete(200, "Hello")
}
}
}
}
The "hello" is always printed, even if the directive is rejected.
I always thought that when a route is rejected it does not continue to inner routes (or at least is how I understand it)
Did I misunderstand something with Spray or there is a bug somewhere in my code?
Thanks you!
[UPDATE 1]
An implementation of directive_always_reject() could be:
def directive_always_reject[T]() : Directive0 = {
reject(
new ValidationRejection("Some error")
)
}
[UPDATE 2]
I see that a solution could be put the println inside the complete function.
path("users") {
post {
entity(as[User]){
user =>
directive_always_reject(){
complete {
println("Hello")
"Hello"
}
}
}
}
}
However this solution does not apply to me because in my real code I pass the RequestContext to another actor who is the one that completes the request.

spray and actor non deterministic tests

Helo,
at the beginning i wold like to apologize for my english :)
akka=2.3.6
spray=1.3.2
scalatest=2.2.1
I encountered strange behavior of teting routes, which asks actors in handleWith directive,
I've route with handleWith directive
pathPrefix("firstPath") {
pathEnd {
get(complete("Hello from this api")) ~
post(handleWith { (data: Data) =>{ println("receiving data")
(dataCalculator ? data).collect {
case Success(_) =>
Right(Created -> "")
case throwable: MyInternalValidatationException =>
Left(BadRequest -> s"""{"${throwable.subject}" : "${throwable.cause}"}""")
}
}})
}
}
and simple actor wchich always responds when receive object Data and has own receive block wrapped in LoggingReceive, so I should see logs when message is receiving by actor
and i test it using (I think simple code)
class SampleStarngeTest extends WordSpec with ThisAppTestBase with OneInstancePerTest
with routeTestingSugar {
val url = "/firstPath/"
implicit val routeTestTimeout = RouteTestTimeout(5 seconds)
def postTest(data: String) = Post(url).withJson(data) ~> routes
"posting" should {
"pass" when {
"data is valid and comes from the identified user" in {
postTest(correctData.copy(createdAt = System.currentTimeMillis()).asJson) ~> check {
print(entity)
status shouldBe Created
}
}
"report is valid and comes from the anonymous" in {
postTest(correctData.copy(createdAt = System.currentTimeMillis(), adid = "anonymous").asJson) ~> check {
status shouldBe Created
}
}
}
}
}
and behavior:
When I run either all tests in package (using Intellij Idea 14 Ultimate) or sbt test I encounter the same results
one execution -> all tests pass
and next one -> not all pass, this which not pass I can see:
1. fail becouse Request was neither completed nor rejected within X seconds ( X up tp 60)
2. system console output from route from line post(handleWith { (data: Data) =>{ println("receiving data"), so code in handleWith was executed
3. ask timeout exception from route code, but not always (among failed tests)
4. no logs from actor LoggingReceive, so actor hasn't chance to respond
5. when I rerun teststhe results are even different from the previous
Is there problem with threading? or test modules, thread blocking inside libraries? or sth else? I've no idea why it isn't work :(

Scala play catch/log java.lang.ExceptionInInitializerError

In Play, if an in thrown in initializing a class - for example, configuration.get("badKey").get being called, I believe there is a java.lang.ExceptionInInitializerError. However, no error is ever caught or logged by Play and it just goes on, broken.
How can I make sure this is caught, or logged, or something other than just ignored?
It brings the website to halt, but I don't know that it's happened.
I know that I shouldn't have these errors in the first place. What first prompted this is that the Application.conf file differs depending on if its my local environment or production. If a developer forgets to add a key to the production one, it can bring the website to a halt (silently). Conceivably, though, there could be other errors too.
You can use play's built in Logger.
import play.Logger
try {
configuration.get("badKey").get
} catch {
case e:ExceptionInInitializerError => {
Logger.error("ExceptionInInitializerError")
Logger.error(e.getMessage())
}
case e:Exception => {
Logger.error("Exception")
Logger.error(e.getMessage())
}
}
Or write an accessor that goes to a default or logs an error without needing a try catch
import play.Logger
import play.api.Play
object Conf {
private val config = Play.current.configuration
def get(key:String):String =
config.getString(key) match {
case Some(value:String) => value
case _ => {
Logger.warn("No value found in application.conf for [" + key + "]")
"some default value"
}
}
}