主要区别:Mockito和JMockIt

use*_*855 10 junit jmockit mocking mockito

这是我最初尝试使用JMockIt时发现的.我必须承认,我发现JMockIt文档非常简洁,因为它提供了什么,因此我可能错过了一些东西.尽管如此,这是我所理解的:

Mockito: List a = mock(ArrayList.class) does not stub out all methods
of List.class by default. a.add("foo") is going to do the usual thing
of adding the element to the list.

JMockIt: @Mocked ArrayList<String> a;
It stubs out all the methods of a by default. So, now a.add("foo")
is not going to work.

This seems like a very big limitation to me in JMockIt.
How do I express the fact that I only want you to give me statistics
of add() method and not replace the function implementation itself
What if I just want JMockIt to count the number of times method  add()
was called, but leave the implementation of add() as is?

I a unable to express this in JMockIt. However, it seems I can do this
in Mockito using spy()
Run Code Online (Sandbox Code Playgroud)

我真的想在这里被证明是错的.JMockit声称它可以做其他模拟框架所做的一切以及更多.在这里似乎不是这样的

@Test
public void shouldPersistRecalculatedArticle()
{
  Article articleOne = new Article();
  Article articleTwo = new Article();

  when(mockCalculator.countNumberOfRelatedArticles(articleOne)).thenReturn(1);
  when(mockCalculator.countNumberOfRelatedArticles(articleTwo)).thenReturn(12);
  when(mockDatabase.getArticlesFor("Guardian")).thenReturn(asList(articleOne, articleTwo));

  articleManager.updateRelatedArticlesCounters("Guardian");

  InOrder inOrder = inOrder(mockDatabase, mockCalculator);
  inOrder.verify(mockCalculator).countNumberOfRelatedArticles(isA(Article.class));
  inOrder.verify(mockDatabase, times(2)).save((Article) notNull());
}



@Test
public void shouldPersistRecalculatedArticle()
{
  final Article articleOne = new Article();
  final Article articleTwo = new Article();

  new Expectations() {{
     mockCalculator.countNumberOfRelatedArticles(articleOne); result = 1;
     mockCalculator.countNumberOfRelatedArticles(articleTwo); result = 12;
     mockDatabase.getArticlesFor("Guardian"); result = asList(articleOne, articleTwo);
  }};

  articleManager.updateRelatedArticlesCounters("Guardian");

  new VerificationsInOrder(2) {{
     mockCalculator.countNumberOfRelatedArticles(withInstanceOf(Article.class));
     mockDatabase.save((Article) withNotNull());
  }};
}
Run Code Online (Sandbox Code Playgroud)

像这样的声明

inOrder.verify(mockDatabase, times(2)).save((Article) notNull());
Run Code Online (Sandbox Code Playgroud)

在Mockito中,在JMockIt中没有等效,正如您从上面的示例中看到的那样

new NonStrictExpectations(Foo.class, Bar.class, zooObj)
{
    {
        // don't call zooObj.method1() here
        // Otherwise it will get stubbed out
    }
};


new Verifications()
{
    {
        zooObj.method1(); times = N;
    }
};
Run Code Online (Sandbox Code Playgroud)

Rog*_*rio 9

事实上,默认情况下,所有模拟API都会模拟或删除模拟类型中的每个方法.我觉得你很困惑mock(type)("完全"嘲笑)和spy(obj)(部分嘲弄).

JMockit可以做到这一切,在每种情况下都使用简单的API.这些都是通过JMockit教程中的示例进行描述的.为了证明,您可以看到示例测试套件(还有更多已从工具包的较新版本中删除,但仍可在旧的zip文件中找到),或许多JMockit集成测试(目前超过一千个) .

相当于Mockito的spy是JMockit中的"动态部分嘲弄".只需将您想要部分模拟的实例作为参数传递给Expectations构造函数.如果没有记录预期,则在执行测试代码时将执行实际代码.顺便说一下,Mockito在这里有一个严重的问题(JMockit没有),因为它总是执行真正的代码,即使它被调用在内部when(...)或者verify(...); 因此,人们必须使用doReturn(...).when(...)以避免对间谍物体的意外.

关于调用的验证,JMockit Verifications API比其他任何API都强大.例如:

new VerificationsInOrder() {{
    // preceding invocations, if any
    mockDatabase.save((Article) withNotNull()); times = 2;
    // later invocations, if any
}};
Run Code Online (Sandbox Code Playgroud)


Lun*_*ore 6

Mockito是一个比JMockIT更老的库,所以你可以期待它有更多的功能.如果您想查看一些记录不太完整的功能,请阅读发布列表.JMockIT的作者已经制作了一个功能矩阵,在这些功能中,他们错过了其他框架所做的所有事情,但却出现了一些错误(例如,Mockito可以进行严格的模拟和排序).

Mockito也被编写为启用单元级BDD.这通常意味着如果您的测试提供了如何使用代码的良好示例,并且如果您的代码可爱且分离且设计良好,那么您将不需要 JMockIT提供的所有恶作剧.在开源中最困难的事情之一是对许多请求说"不",这些请求从长远来看没有帮助.

比较MockitoJMockIT头版的例子,看看真正的区别.这不是关于你测试的内容,而是关于你的测试记录和描述类的行为的程度.

兴趣声明: Szczepan和我在撰写Mockito初稿时处于同一个项目之后,看到我们中的一些人推出了我们自己的存根类而不是使用当时现有的模拟框架.所以我觉得他为我写了这一切,并且完全有偏见.谢谢Szczepan.

  • 我很抱歉,但你做错了很多事情。如果您认为 JMockit 没有其他工具可以做的事情,请给我看一个测试。我已经提供了证据:请参阅示例测试套件以在 JMockit 和 Mockito 之间进行比较,使用等效的测试对,包括在 Mockito 站点中找到的*所有*测试。(如果我错过了,请告诉我。) Mockito 不支持 *strict* 模拟,即那些报告缺少和意外调用而没有额外验证码的模拟。关于对优秀设计的支持,恰恰相反:Mockito 阻止了它。 (2认同)
  • Lunivore,我不仅花了数百个小时研究 Mockito,还研究了所有其他 Java 模拟工具(还花了一些时间研究 C++、.NET、Ruby 和 Python 模拟工具)。例如,我知道人们经常遇到 Mockito 的局限性,并要求添加支持(请参阅问题 12、101 和 130,或邮件列表中的帖子,例如:http://groups.google.com /group/mockito/browse_thread/thread/ef0617e3fda6e8d5)。有关社区参与 JMockit 项目的证据,请查看问题、“JMockit 用户”讨论组或更改历史记录页面。 (2认同)
  • 关于对良好 OO 设计实践的支持,我创建 JMockit 正是因为现有工具(EasyMock 和 jMock,到 2005 年底)缺乏,现在仍然存在。使用“传统的”模拟 API,我不能: a) 对碰巧使用静态持久性外观的类进行单元测试,即使这种特殊模式在现实世界中对我(和同事)来说非常有效;b) 遵循几乎所有 API 设计书籍中关于正确使用继承的建议。我在“关于 JMockit”页面和 JMockit 教程中写了关于此类设计主题的文章。 (2认同)
  • 我也更喜欢组合。使用 JMockit,开发人员可以适当地设计扩展,使类或方法为“final”,以表明它们不应被继承;这鼓励使用组合,而不会降低编写单元测试的能力。我很少使用单例,但是静态方法可以起到很好的作用,就像我提到的那样,或者作为构造函数的替代品;JMockit 使开发人员可以自由决定是否使用它们,而无需成为纳粹分子。我的优秀设计理念与 Fowler、Bloch、McConnel 等作者的理念一致。 (2认同)