用Java创建模拟对象的最佳框架是什么?为什么?每个框架的优缺点是什么?

#1 楼

我使用Mockito取得了成功。

当我尝试学习JMock和EasyMock时,我发现学习曲线有些陡峭(尽管也许就是我)。

我喜欢Mockito,因为它的语法简洁明了,我很快就能掌握。最小的语法旨在很好地支持常见情况,尽管有几次我需要做一些更复杂的事情,但我发现我想要的东西是受支持的并且易于理解。来自Mockito主页:

import static org.mockito.Mockito.*;

List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();


没有比这更简单的了。它不会模拟静态方法。

评论


美丽。对于静态方法,只需将Mockito与JMockit结合使用,实际上没有太多的“旧版”类可供您进行测试。

– Epaga
09年3月13日在14:26

我喜欢当您尝试执行不应该做的事情时(例如,内联创建模拟),如何在异常消息中清楚地说明您做错了什么。

–ripper234
09年6月27日在12:00

对我来说,绝对。我仍然无条件推荐它。当然,如果您找到另一个更能满足您需求的框架,请在另一个答案中提及它,并查看它获得了哪些票数以及收到了什么样的评论。

–布赖恩·拉弗兰布瓦兹(Brian Laframboise)
2011年3月2日在15:24

@MexicanHacker为什么您不能在Android上使用它?我现在和Robolectric一起使用。

–伊尔卡
2011年3月19日在18:57



我正在使用Mockito并喜欢它!很棒的文档(很少找到这种质量的文档,作者的出色工作),这对于我们使用内容而不必深入研究框架的代码是如此重要!!!

–雷纳托
2012年3月8日在7:37

#2 楼

我是PowerMock的创建者,因此显然我必须建议这样做! :-)

PowerMock扩展了EasyMock和Mockito的功能,能够模拟静态方法,最终方法甚至私有方法。 EasyMock支持已完成,但Mockito插件需要更多工作。我们还计划增加对JMock的支持。

PowerMock并不是要替换其他框架,而是可以在其他框架不允许模拟的棘手情况下使用。 PowerMock还包含其他有用的功能,例如禁止使用静态初始化程序和构造函数。

评论


对于在主机PC上使用本机Java的Android应用程序进行单元测试,Powermock是必不可少的(避免使用慢速模拟器)

– Jeff Axelrod
2011年7月14日在18:08

@Jan唯一的问题是尽管使用Robolectric时PowerMock不兼容:-(我想做@RunWith(PowerMockRunner.class)和@RunWith(RobolectricTestRunner.class)

–布伦德尔
11-10-22在0:29



在过去几个月使用PowerMock之后,我衷心推荐它!

–cwash
2012年1月3日19:59

PowerMock确实很棒。我真的很喜欢静态单例访问所有内容,这使得测试成为可能。

–伊恩·马卡里纳奥(Ian Macalinao)
2012年3月17日在8:42

注意:某些模拟最终方法之类的东西仅在Powermock中适用于EasyMock而不适用于Mockito。当您不经常使用它时,这有点麻烦。我想知道为什么有些东西不起作用,然后才意识到它只在doco的Easymock部分下列出。

–trafalmadorian
2013年12月4日23:57

#3 楼

JMockit项目站点包含有关当前模拟工具包的大量比较信息。

尤其要查看功能比较矩阵,其中包括EasyMock,jMock,Mockito,Unitils Mock,PowerMock,当然还有JMockit。我会尽量保持其准确性和最新性。

评论


JMockit给我留下了深刻的印象,它的学习曲线更陡峭,但是多年来它的文档非常好,并且可以模拟任何东西。我从Mockito开始,它很容易学习,但是我经常遇到一些我无法解决的问题。另一方面,我什至无法想象JMockit不可能做到的事情。

–HontváriLevente
2015年4月16日15:39



#4 楼

我在JMockit上取得了成功。

它是一个很新的东西,所以它有点原始且文档不足。它使用ASM动态地重新定义类字节码,因此它可以模拟出所有方法,包括静态,私有,构造函数和静态初始化程序。例如:

import mockit.Mockit;

...
Mockit.redefineMethods(MyClassWithStaticInit.class,
                       MyReplacementClass.class);
...
class MyReplacementClass {
  public void $init() {...} // replace default constructor
  public static void $clinit{...} // replace static initializer
  public static void myStatic{...} // replace static method
  // etc...
}


它还具有Expectations接口,允许记录/播放场景:缺点是它需要Java 5/6。

评论


是的,真的可以推荐这个

– Epaga
08-10-22在9:49

只是更新:JMockit项目移至code.google.com/p/jmockit。自从这篇文章发布以来,它已经发展了很多(并且还在不断发展),现在拥有大量的文档。

–罗杰里奥
09年12月27日在1:18

JMockit又搬了。现在可以在Github上使用。 jmockit.github.io

–拉维(Ravi K)Thapliyal
2015年2月8日14:55

#5 楼

您也可以看看使用Groovy进行测试。在Groovy中,您可以使用'as'运算符轻松模拟Java接口:

def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest 


除了此基本功能之外,Groovy在模拟方面还提供了更多功能,包括强大的功能。 MockForStubFor类。

http://docs.codehaus.org/display/GROOVY/Groovy+Mocks

#6 楼

我开始在EasyMock中使用模拟。很容易理解,但是重播步骤有点烦人。 Mockito删除了此内容,并且语法更简洁,因为看起来可读性是其主要目标之一。我不能足够强调它的重要性,因为大多数开发人员将花费时间阅读和维护现有代码,而不是创建代码。

另一个好处是,接口和实现类的处理方式相同,与EasyMock不同,在EasyMock中,您仍然需要记住(并检查)以使用EasyMock类扩展。 />最近,我快速浏览了JMockit,尽管功能清单非常全面,但我认为这样做的代价是所生成代码的可读性,并且必须编写更多代码。

对我来说,Mockito达到了最佳的位置,易于编写和阅读,并且可以处理大多数代码所需的大多数情况。将Mockito与PowerMock一起使用将是我的选择。

要考虑的一件事是,如果您是自己开发的,或者是在紧密的小型团队中开发的,则可能不是最佳选择获得一家拥有不同技能水平的开发人员的大型公司。在后一种情况下,需要更多考虑可读性,易用性和简单性。如果很多人最终不使用它或不维护测试,那么获得最终的模拟框架毫无意义。

评论


+1此答案需要更多投票。一个人应该分享他们真正喜欢或不喜欢的框架。只是“我用过它。。我喜欢它!”这是为什么如此好的问题无法获得SO的原因之一。

–拉维(Ravi K)Thapliyal
2015年2月8日14:52

#7 楼

我们在工作中大量使用EasyMock和EasyMock类扩展,对此感到非常满意。它基本上可以为您提供所需的一切。看一下文档,有一个非常好的示例,向您展示了EasyMock的所有功能。

评论


在我的问题中,我更多地是在寻找您喜欢和不喜欢模拟框架的东西。我可以找到文档并阅读所有内容-我想知道使用它的人对此有何看法。

–乔什·布朗(Josh Brown)
08年9月7日在23:44

EasyMock仅适用于Java 5及更高版本,哎呀!

–马特b
08-12-5 18:50

#8 楼

我很早就使用过JMock。我在上一个项目中尝试过Mockito并喜欢它。更简洁,更干净。 PowerMock涵盖了Mockito中不存在的所有需求,例如模拟静态代码,模拟实例创建,模拟最终类和方法。因此,我拥有完成工作所需的一切。

#9 楼

我喜欢JMock,因为您能够设定期望。这与检查是否在某些模拟库中找到了一种方法完全不同。使用JMock可以编写非常复杂的期望。请参见jmock作弊技巧。

#10 楼

是的,Mockito是一个很好的框架。我将其与hamcrest和Google guice结合使用来设置测试。

#11 楼

最好的模拟解决方案是让机器通过基于规范的自动化测试来完成所有工作。对于Java,请参阅ScalaCheck和Functional Java库中包含的Reductio框架。使用基于规范的自动化测试框架,您可以提供被测方法的规范(应为真的属性),并且该框架会自动生成测试以及模拟对象。

例如,以下属性测试Math.sqrt方法以查看任何正数n平方的平方根是否等于n。

val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }


调用propSqrt.check()时,ScalaCheck生成数百个整数并检查每个整数的属性,还自动确保边缘情况被很好地覆盖。用它编码。 Functional Java中的Reductio框架是具有相同概念的纯Java实现。

#12 楼

Mockito还提供以下选项:对方法进行存根,匹配参数(例如anyInt()和anyString()),验证调用次数(times(3),atLeastOnce(),never())等。

我还发现Mockito很简单干净。

我不喜欢Mockito的一件事是您不能对静态方法进行存根。

评论


这个答案是不正确的。您不仅限于与jMock的接口。您可以使用ClassImposteriser模拟具体的类。

–铁氟龙泰德
08-09-12 at 2:59

您也可以使用EasyMock进行完全相同的操作。

–Cem Catikkas
08-09-14在5:27

我已从答案中删除了错误之处。

–乔什·布朗(Josh Brown)
2010-3-11在18:48

#13 楼

如果有所不同,则可以使用JtestR中结合使用的JRuby和Mocha,以表达性和简洁的Ruby为Java代码编写测试。这里有一些有用的JtestR模拟示例。这种方法的一个优点是模拟具体类非常简单。

#14 楼

我开始通过JMock使用模拟,但最终过渡为使用EasyMock。 EasyMock就是这样,更加轻松,并且提供了一种更加自然的语法。从那以后我还没有切换。