gpt4 book ai didi

scala - 如何使用 Mockito 验证 Specs2 中特定字符串匹配器的调用

转载 作者:行者123 更新时间:2023-12-02 03:24:24 26 4
gpt4 key购买 nike

我有一个这样的测试:

httpClient.post(anyString, anyString) returns (first, second)

//do my thing

there were two(httpClient).post(anyString, anyString)

这工作正常,但我想验证第一个调用是否传递了与第二个调用不同的主体。体量比较大,我不想在严格的例子上做精确匹配。我试过这个:

there was one(httpClientMock).postMessage(anyString, argThat(contain("FOO"))
there was one(httpClientMock).postMessage(anyString, argThat(contain("FOO"))

这让 Mockito 提示:

InvalidUseOfMatchersException: 
[error] Invalid use of argument matchers!
[error] 2 matchers expected, 3 recorded:

我也尝试过:

  there was one(httpClientMock).postMessage(argThat(contain("foo")), argThat(contain("FOO")))
there was one(httpClientMock).postMessage(argThat(contain("foo")), argThat(contain("FOO")))

结果是:

Wanted 1 time:
[error] -> ...
[error] But was 2 times. Undesired invocation: ...

在我看来,这样的事情应该是可能的,但我似乎无法弄清楚。见解?

最佳答案

我认为这首先是 Mockito 的问题。当您使用带有specs2的Mockito并且有疑问时,请始终下拉至直接Mockito API:

// simplified httpClient with only one parameter
val httpClient = mock[HttpClient]
httpClient.post(anyString) returns ""

httpClient.post("s1")
httpClient.post("s2")

// forget specs2
// there was two(httpClient).post(anyString)

org.mockito.Mockito.verify(httpClient, org.mockito.Mockito.times(1)).post("s1")

// I guess that you don't want this to pass but it does
org.mockito.Mockito.verify(httpClient, org.mockito.Mockito.times(1)).post("s1")

解决此问题的一种可能方法是定义一个匹配器来检查参数的连续值:

there was two(httpClient).post(consecutiveValues(===("s1"), ===("s2")))

consecutiveValues 匹配器定义如下:

import matcher._
import MatcherImplicits._

// return a matcher that will check a value against a different
// `expected` matcher each time it is invoked
def consecutiveValues[T](expected: Matcher[T]*): Matcher[T] = {
// count the number of tested values
var i = -1

// store the results
var results: Seq[(Int, MatchResult[T])] = Seq()

def result(t: T) = {
i += 1
// with Mockito values are tested twice
// the first time we return the result (but also store it)
// the second time we return the computed result
if (i < expected.size) {
val mr = expected(i).apply(Expectable(t))
results = results :+ (i, mr)
mr
} else results(i - expected.size)._2
}

// return a function that is translated to a specs2 matcher
// thanks to implicits
// display the failing messages if there are any
(t: T) => (result(t).isSuccess,
results.filterNot(_._2.isSuccess).map { case (n, mr) =>
s"value $n is incorrect: ${mr.message}" }.mkString(", "))
}

您可以测试上面的代码。失败消息不是最好的,但可以解决问题。在这种情况下:

httpClient.post("s1") 
httpClient.post("s2")

there was two(httpClient).post(consecutiveValues(===("s1"), ===("s3")))

你会看到:

[error] x test
[error] The mock was not called as expected:
[error] httpClient.post(
[error] value 1 is incorrect: 's2' is not equal to 's3'
[error] );
[error] Wanted 2 times:
[error] -> at ...
[error] But was 1 time:
[error] -> at ...

关于scala - 如何使用 Mockito 验证 Specs2 中特定字符串匹配器的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15173180/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com