如何验证一个方法被一个对象调用,该对象的某些字段可能是 anyObject() 而其他字段具有特定值?
How to verify a method gets called with an object whose some fields may be anyObject() while others have a specific value?
我将 Mockito 与 ScalaTest 一起使用。考虑这个简化的例子。
模型案例class:
case class Batch(batchId: Long,
timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
invoicesReceived: Option[Int])
在我的测试中,我正在模拟一个名为 BatchRepository 的 class,它有一个带有此签名的方法:
def create(conn: Connection, batch: Batch): Long
测试代码相关位:
verify(batchRepository, times(1)).create(anyObject(),
Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
)
重点是:我想验证被测代码是否使用任何 Connection 和具有任何 ID 和时间戳的 Batch 实例调用模拟存储库方法,但是 invoicesReceived
正好是 Some(1)
。
使用 Mockito,这是否可能,如果可能,如何实现?
生产代码创建了一个新的 Batch,它将时间戳设置为当前时刻,因此我认为几乎不可能在 verify()
调用的测试中使用完全相同的时间戳创建真正的 Batch 对象。所以至少对于我需要的时间戳 anyObject()
.
我尝试了很多变体,比如将整个批次包装在 Matchers.eq()
中,但我还没有找到任何有效的方法:
Invalid use of argument matchers! 2 matchers expected, 4 recorded [...]
如果事实证明有一些替代方法可以使用 Mockito 来测试我想要的东西,我很高兴听到我使用的匹配器完全错误。
(我很难为这个问题写一个好名字;如果你明白我在问什么并且可以更简洁地表达它,请编辑或发表评论。)
问题是您试图同时 verify
两个调用 - create
和 Batch.apply
。不能那样做。
做你想做的一种方法是 ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
你试过mockito-scala了吗?它支持部分函数作为匹配器,所以你可以只写
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
如果您使用惯用的语法甚至更好
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called
我将 Mockito 与 ScalaTest 一起使用。考虑这个简化的例子。
模型案例class:
case class Batch(batchId: Long,
timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
invoicesReceived: Option[Int])
在我的测试中,我正在模拟一个名为 BatchRepository 的 class,它有一个带有此签名的方法:
def create(conn: Connection, batch: Batch): Long
测试代码相关位:
verify(batchRepository, times(1)).create(anyObject(),
Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
)
重点是:我想验证被测代码是否使用任何 Connection 和具有任何 ID 和时间戳的 Batch 实例调用模拟存储库方法,但是 invoicesReceived
正好是 Some(1)
。
使用 Mockito,这是否可能,如果可能,如何实现?
生产代码创建了一个新的 Batch,它将时间戳设置为当前时刻,因此我认为几乎不可能在 verify()
调用的测试中使用完全相同的时间戳创建真正的 Batch 对象。所以至少对于我需要的时间戳 anyObject()
.
我尝试了很多变体,比如将整个批次包装在 Matchers.eq()
中,但我还没有找到任何有效的方法:
Invalid use of argument matchers! 2 matchers expected, 4 recorded [...]
如果事实证明有一些替代方法可以使用 Mockito 来测试我想要的东西,我很高兴听到我使用的匹配器完全错误。
(我很难为这个问题写一个好名字;如果你明白我在问什么并且可以更简洁地表达它,请编辑或发表评论。)
问题是您试图同时 verify
两个调用 - create
和 Batch.apply
。不能那样做。
做你想做的一种方法是 ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
你试过mockito-scala了吗?它支持部分函数作为匹配器,所以你可以只写
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
如果您使用惯用的语法甚至更好
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called