Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito scala verification tests not working (play framework)

I'm trying out unit testing with Play framework in scala. I've written a class that checks whether the config is correct (I have a bit more error handling but I actually use this code for my test now):

class TaskQueueConfig(conf: Configuration) {
  val schedulingEnabled = conf.getBoolean("schedulingEnabled").get
  val processingEnabled = conf.getBoolean("processingEnabled").get
  val queueName = conf.getString("queue").get
}

I'm testing this using play 2.1.1's default test setup:

class ConfigTestSpec extends Specification with Mockito with CalledMatchers {
  "TaskQueueConfig" should {
     "verify calls" in {
      val tqConf = mock[Configuration]
      tqConf.getString("queue") returns Some("queueName")
      tqConf.getBoolean("schedulingEnabled") returns Some(true)
      tqConf.getBoolean("processingEnabled") returns Some(true)
      Logger.error("setup done")

      val config = new TaskQueueConfig(tqConf)

      there was one(tqConf).getString("queue")
      there were two(tqConf).getBoolean(any[String])
      there were one(tqConf).getBoolean("schedulingEnabled")
      there were one(tqConf).getBoolean("processingEnabled")
    }
  }
}

I'm getting the following error:

[error] x verify calls
[error]    The mock was not called as expected:
[error]    configuration.getString$default$2();
[error]    Wanted 1 time:
[error]    -> at config.ConfigTestSpec$$anonfun$2$$anonfun$apply$4$$anonfun$apply$12.apply(ConfigTestSpec.scala:61)
[error]    But was 2 times. Undesired invocation:
[error]    -> at config.TaskQueueConfig.<init>(TaskQueueConfig.scala:10) (ConfigTestSpec.scala:61)

This is very strange, because the code is very isolated and there is clearly just 1 conf.getString call in TaskQueueConfig. Line 10 is the line with the getString method on it. Line 61 is the line with "there was one(tQConf).getString"

How can I fix this issue?

(there is no difference between were and was).

PS: I know this example is pretty useless to test, but I have more complex configs where there are some rules that need to be tested.

UPDATE 1 The getString method has two parameters, the second parameter has a default value of None (it's type is Option[Set[String]]). When I explicitly add the None's to the setup and verification, it still doesn't work. But when I add null instead, I get it working.

  val tqConf = mock[Configuration]

  tqConf.getString("queue", null) returns Some("queueName")
  tqConf.getBoolean("schedulingEnabled") returns Some(true)
  tqConf.getBoolean("processingEnabled") returns Some(true)

  val c = new TaskQueueConfig(tqConf)

  there was one(tqConf).getString("queue", null)
  there was one(tqConf).getString(any[String], any[Option[Set[String]]])
  there were two(tqConf).getBoolean(any[String])
  there was one(tqConf).getBoolean("schedulingEnabled")
  there was one(tqConf).getBoolean("processingEnabled")

  c.processingEnabled must beTrue
  c.schedulingEnabled must beTrue
  c.queueName must be("queueName")

So I guess the question now is, why do I have to use null?

like image 263
Jaap Avatar asked Sep 05 '13 13:09

Jaap


1 Answers

You have to use null in the two-argument getString() call because Mockito requires you to either use use matchers for all arguments or none at all.

So mixing "queue" (a literal) with any[Option[Set[String]]] (a matcher) won't work. Sometimes Mockito can work out that you've done that and it gives you an error, but it seems like you're unlucky here...

Try using matchers in all positions like this:

tqConf.getString(org.mockito.Matchers.eq("queue"), any[Option[Set[String]]]) returns Some("queueName")

And verifying:

there was one(tqConf).getString(eq("queue"), any[Option[Set[String]]])
like image 196
millhouse Avatar answered Nov 14 '22 17:11

millhouse