8

scala で Play フレームワークを使用して単体テストを試みています。構成が正しいかどうかをチェックするクラスを作成しました (もう少しエラー処理がありますが、実際にはこのコードをテストに使用しています)。

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

play 2.1.1 のデフォルトのテスト設定を使ってこれをテストしています:

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")
    }
  }
}

次のエラーが表示されます。

[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)

コードは非常に分離されており、TaskQueueConfig には明らかに conf.getString 呼び出しが 1 つしかないため、これは非常に奇妙です。行 10 は、getString メソッドを含む行です。61 行目は「there was one(tQConf).getString」の行です。

この問題を解決するにはどうすればよいですか?

(あったとあったの間に違いはありません)。

PS: この例はテストするのにかなり役に立たないことはわかっていますが、テストする必要があるいくつかのルールがあるより複雑な構成があります。

UPDATE 1 getString メソッドには 2 つのパラメーターがあり、2 番目のパラメーターのデフォルト値は None です (タイプは Option[Set[String]])。None をセットアップと検証に明示的に追加しても、まだ機能しません。しかし、null代わりに追加すると、機能します。

  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")

では、なぜ null を使用する必要があるのでしょうか。

4

1 に答える 1

4

Mockitoでは、すべての引数に use matcher を使用するか、まったく使用しない必要があるため、2 つの引数の呼び出しで使用する必要がありnullます。getString()

"queue"そのため、 (リテラル) と(マッチャー) を混在させても機能しany[Option[Set[String]]]ません。Mockitoは、ユーザーがそれを実行したことを認識してエラーを返すことがありますが、ここでは運が悪いようです...

次のように、すべての位置でマッチャーを使用してみてください。

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

そして検証:

there was one(tqConf).getString(eq("queue"), any[Option[Set[String]]])
于 2013-09-09T06:23:20.767 に答える