模拟返回任意参数的存根结果

时间:2013-09-04 14:51:00

标签: scala mockito specs2

通过以下测试,我的存根设置无效。模拟requestBuilder使用参数"INCORRECT"存根,而被测试的类则使用"/socket"调用它。

我在JUnit中使用Mockito的经验告诉我,运行时的调用将导致null。但是,我看到了误报。测试通过& requestBuilder正在返回模拟request,即使它是使用"/socket"调用的。

这是为什么?是否与多个期望有关?如果是这样,最终的期望是重要的,失败。

class ChannelSpec extends Specification with Mockito with ScalaCheck with ArbitraryValues { def is = s2"""

  A Channel must
    send an open request to /socket with provided channel name on instantiation $sendToSocket

"""

  def sendToSocket = prop{(name: String, key: Key, secret: Secret) =>
    val requestBuilder = mock[(String, Seq[Map[String, String]]) => Req]
    val request = mock[Req]
    val httpRequestor = mock[(Req) => Future[String]]
    val result = mock[Future[String]]

    val params = Seq(Map("key" -> key.value, "timestamp" -> anyString, "token" -> anyString), Map("channel" -> name))
    requestBuilder("INCORRECT", params) returns request
    httpRequestor(request) returns result
    new Channel(name, key, secret, requestBuilder = requestBuilder, httpRequestor = httpRequestor)
    there was one(requestBuilder).apply("INCORRECT", params)
    println("expecting " + request)
    there was one(httpRequestor).apply(request)
  }

2 个答案:

答案 0 :(得分:1)

虽然我不了解Scala,但我知道anyString没有按照您的想法行事。具体来说,all Mockito matchers work through side effects,正如我在this SO answer末尾所描述的那样,将相关的String对象添加到ArgumentMatcherStorage

因此,您无法真正将匹配器提取为变量:

// This is fine, because the parameters are evaluated in order.

takesTwoParameters(eq("A"), eq("B")) returns bar

// Now let's change it a little bit.

val secondParam = eq("SECOND")
val firstParam = eq("FIRST")

// At this point, firstParam == secondParam == null, and the hidden argument
// matcher stack looks like [eq("SECOND"), eq("FIRST")]. That means that your
// stubbing will apply to takesTwoParameters("SECOND", "FIRST"), not
// takesTwoParameters("FIRST", "SECOND")!

takesTwoParameters(firstParam, secondParam)) returns bar

此外,您不能将anyString嵌套到Seq或Map等任意类型中; Mockito的参数匹配器旨在匹配整个参数。

您最好的选择是使用argThat作为参数,并创建一个小的Hamcrest匹配器,检查您正在检查的参数是否正确形成。这将使您可以灵活地检查您的参数是否与您期望的大致相同,而忽略了您不关心的值。

答案 1 :(得分:1)

我认为这只是一种表现形式,在接受规范中,没有例外表明失败的期望。所以你有:

def test = {
  1 === 2
  1 === 1
}

然后test将通过,因为只有最后一个值将保留为测试结果。您可以通过链接期望来改变这种行为:

def test = {
  (1 === 2) and
  (1 === 1)
}

或者通过在规范中混合ThrownExpectations特征:

import org.specs2.Specification
import org.specs2.matcher.ThrownExpectations
import org.specs2.mock.Mockito

class MySpec extends Specification with ThrownExpecations with Mockito {
  ...
}