代码之家  ›  专栏  ›  技术社区  ›  Jonik

如何验证用对象调用的方法,该对象的某些字段可以是anyObject(),而其他字段具有特定的值?

  •  0
  • Jonik  · 技术社区  · 7 年前

    我用的是mockito和scalatest。考虑这个简化的例子。

    模型案例类:

    case class Batch(batchId: Long, 
                     timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
                     invoicesReceived: Option[Int])
    

    在我的测试中,我模拟了一个名为batchrepository的类,该类具有以下签名的方法:

    def create(conn: Connection, batch: Batch): Long
    

    测试代码相关位:

    verify(batchRepository, times(1)).create(anyObject(),
      Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
    )
    

    牛肉是 :我想验证测试中的代码是否使用任何连接和具有任何ID和时间戳的批处理实例调用模拟存储库方法,但是 invoicesReceived 正是 Some(1) .

    使用mockito,这有可能吗?如果有,怎么可能?

    生产代码创建了一个新的批,它将时间戳设置为当前时刻,因此我认为在测试中几乎不可能为 verify() 使用完全相同的时间戳调用。所以至少我需要时间戳 anyObject() .

    我试过很多变种,比如把整批包装起来 Matchers.eq() 但是我没有找到任何有用的东西:

    参数匹配器的使用无效!应输入2个匹配项,记录4个[…]

    我很高兴听到我用的火柴都是错的,如果有其他方法可以用Mockito测试我想要的。γ射线

    (我很难给这个问题起个好名字;如果你理解我的要求并能更简洁地表达,请编辑或发表评论。)

    2 回复  |  直到 7 年前
        1
  •  1
  •   Dima    7 年前

    问题是你试图 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)`
    
        2
  •  0
  •   ultrasecr.eth    7 年前

    你试过了吗 mockito-scala ?它支持作为匹配器的部分函数,这样您就可以编写

    verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
    

    或者更好的方法是使用惯用语法

    batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called