如何让Mockito返回特定的实例?

时间:2014-01-02 23:11:14

标签: mockito

我无法判断这是否支持功能。我想模拟一个对象被提供给模拟方法时的行为。 Examples for "when"给出了文档中的整数或字符串,但可以为对象完成。是否需要为每个所需的返回对象定义custom matcher类?

Class Point
   Point (int X, int Y)

Class ItemMover
   goEast(Point p) {
      return new Point(p.getX() + 1, p.getY())

Class App
   ItemMover itemMover
   Point currentPosition
   main() {
      def p1 = new Point(1,1)
      currentPosition = itemMover.goEast(p1)

Class AppTest
      def itemMover = Mock(ItemMover)
      def p1 = new Point(1,1)
      def p2 = new Point(2,1)
      when(itemMover.goEast(p1)).thenReturn(p2)
      app.main()
      assertEquals(app.currentPosition.getX(), 2)

更新:根据以下答案。当X和Y相等时,需要实现对象的equals和hashCode方法以将等式计算为p1.equals(p2)。

2 个答案:

答案 0 :(得分:1)

您可以将具体参数以及参数匹配器与任何对象一起使用。所以这应该可以正常工作。

when(mockPoint.goEast(p1)).thenReturn(p3)

p3用作参数时,它将模拟配置为返回p1。要将它与参数匹配器结合使用(因为具体的参数和匹配器可能不会混合),我通常使用默认的eq匹配器。

// assuming a second goEast method with an int parameter
when(mockPoint.goEast(eq(p1), anyInt())).thenReturn(p3)

答案 1 :(得分:1)

  1. 是的,您可以像返回原始值一样返回对象实例。

  2. 只要覆盖有问题的对象(Point)上的equalshashCode,就不需要自定义匹配器。默认情况下,或使用eq匹配器,Mockito将使用对象的equals方法来确定对象是否相等 - 如果没有覆盖,则只有相等的引用(==)将被视为相等。如果任何一个点(2,3)等于任何其他点(2,3),这是表达它的正确的地点和时间。

    Point是覆盖equalshashCode的特别好的候选者,因为点等式定义明确且易于计算,并且不依赖于外部服务或数据。对于比Point更棘手的对象,参数匹配器是一个很好的解决方案。

  3. 正如tieTYT所提到的,在断言中调用存根方法很少见。对于任何给定的测试,确保您知道正在测试哪个单一系统或对象,使用 该对象的mocks为其提供可预测的环境,然后测试您是否获得了预期值或预期的调用嘲笑。在断言中调用模拟通常会导致混乱,脆弱或重言式测试。

    在这里,如果你正在测试Point,你可能不需要模拟 - 尤其不是模拟点。如果您正在测试Maze,您仍然不需要模拟点,因为您可以使用真实的测试点。但是,测试游戏可能需要一个模拟迷宫,所以如果迷宫是复杂的或随机的,你的测试可能更简单和确定。