Mock正在返回任意参数的存根结果



在下面的测试中,我有一个无效的存根设置。模拟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)
  }

虽然我不了解Scala,但我知道anyString并不像你想象的那样。具体来说,所有Mockito匹配器都会处理副作用,将相关的String对象添加到ArgumentMatcherStorage中,正如我在本SO答案末尾所描述的那样。

因此,您无法真正将匹配符提取到变量中:

// 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匹配器来检查您正在检查的参数是否正确形成。这将使您能够灵活地检查参数是否大致符合您的期望,同时忽略您不关心的值。

我认为这只是一种表现,即在验收规范中,没有异常情况表明预期失败。所以你有:

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 {
  ...
}

相关内容

  • 没有找到相关文章

最新更新