我可以在实例化时设置一个具有期望(验证)的Mockito模拟吗?

时间:2016-03-24 00:04:38

标签: java unit-testing mocking mockito

验证在Mockito中运行的预期方法通常是这样的:

#include <stdio.h>

class Color
{
public:
  Color(unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v) : r(_r), g(_g), b(_b), u(_u), v(_v) {}

  unsigned int r, g, b, u, v;
  static Color* getInstance (unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v);
};

Color* Color::getInstance(unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v)
{
  return new Color(_r, _g, _b, _u, _v);
}

class Printer
{
public:
  Printer() {}
  ~Printer() {}
  static Printer* getInstance();
  void print(Color *c);
};

Printer* Printer::getInstance()
{
  return new Printer();
}

void Printer::print(Color *c)
{
  printf("(%d, %d, %d, %d, %d)\n", c->r, c->g, c->b, c->u, c->v);
}

在创建模拟时,我有什么方法可以指定验证。在像EasyMock这样的东西我可以做:

when(mockFoo.someMethod()).thenReturn(someValue);
// run test
verify(mockFoo, times(n)).someMethod();

我的用例是我有一个常用的测试依赖项,我想模拟(doFooMethodAndReturnBar5Times模拟),但是对于Mockito,我没有办法对其强制执行验证。

1 个答案:

答案 0 :(得分:4)

更新:此答案发生了重大变化,因为Mockito 2中提供了严格的模拟,默认情况下Mockito 3中可以使用严格存根的强制执行。使用strict和{{ 1}}模式来配置这些模拟和存根,并查看mockito issue 769以获取文档和进度。

在Mockito 2之前,这不是Mockito可以轻易做到的事情。 EasyMock的默认严格模拟确保(1)意外交互立即失败,(2)所有预期的交互发生;除了lenient之外,Mockito还没有设置任何设置(它不会立即失败,而是在测试结束时)。这是philosophical design decision on Mockito's part,请参阅this thread Mockito发起人进一步讨论的内容。

事实上,Mockito的verifyNoMoreInteractions语法取决于它允许意外的互动,因为意外的互动告诉Mockito调用了哪种方法:

when

容忍意外电话的EasyMock模拟被称为“漂亮的模拟”; Mockito的一大卖点是默认情况下模拟很好,因此它们通常容忍与被测试行为无关的调用。这确实使调试变得更加困难,因为Mockito不会像EasyMock那样立即在意外的交互中失败,但它也会使测试变得不那么脆弱 - 因为EasyMock模拟,安全更改更可能会破坏测试得到一个意外的电话。 在继续之前,请与您的团队确认他们会对您的选择感到满意:严格的模拟语义对于Mockito来说是相对较新的而且可能会有很大的假设作为框架变革的交易。 (到那时,在看到替代方案后,他们可能会让你使用EasyMock!)

要在Mockito 2 +中使用严格的模拟,,请参阅syntax and libraries in Mockito issue 769。这可能是从Mockito 1.x升级的一个很好的理由。

要在Mockito 1.x中模拟严格的模拟,您需要设置一个未通过测试的默认答案,并且仅使用when(mockFoo.someMethod()).thenReturn(someValue); // ^^^^^^^^^^^^^^^^^^^^ Java calls this first to get an argument for when, // which is how Mockito knows which method to stub: // it's always the last one called. 方法建立正确的行为({ {1}},doVerbdoAnswer等)。此语法为Mockito提供了停用存根行为所需的警告。要创建默认答案,您可以为单个方法设置行为(首选),也可以为单个模拟设置所有方法。

doReturn

Mockito将始终在最后定义的匹配链上返回行为,并且仅在没有链匹配时才使用默认答案,因此您应该能够使用doThrow方法定义任意数量的链来覆盖该行为