什么是Java最好的模拟框架?

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

我用Mockito取得了很好的成功。

当我尝试了解JMock和EasyMock时,发现学习曲线有些陡峭(尽pipe也许这只是我)。

我喜欢Mockito,因为它简单而干净的语法,我能很快掌握。 最简单的语法是为了支持常见的情况而devise的,虽然有些时候我需要做更复杂的事情,但是我发现我想要的东西是被支持的,而且容易理解。

以下是Mockito主页中的一个(删节)示例:

import static org.mockito.Mockito.*; List mockedList = mock(List.class); mockedList.clear(); verify(mockedList).clear(); 

这并没有比这更简单。

我能想到的唯一主要缺点是它不会嘲讽静态方法。

我是PowerMock的创造者,所以显然我必须推荐! 🙂

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

PowerMock并不是要replace其他的框架,而是可以用在其他框架不允许嘲讽的棘手的情况下。 PowerMock还包含其他有用的function,如抑制静态初始化和构造函数。

JMockit项目网站包含了大量的当前嘲笑工具包的比较信息。

特别是,请查看function比较matrix ,其中涵盖了EasyMock,jMock,Mockito,Unitils Mock,PowerMock,当然还有JMockit。 我尽可能地保持准确和最新。

我已经与JMockit成功。

这是相当新的,所以这是有点原始和不足。 它使用ASM来dynamic地重新定义类字节码,所以它可以模拟出包括静态,私有,构造函数和静态初始值设定项在内的所有方法。 例如:

 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... } 

它有一个允许logging/回放场景的期望界面:

 import mockit.Expectations; import org.testng.annotations.Test; public class ExpecationsTest { private MyClass obj; @Test public void testFoo() { new Expectations(true) { MyClass c; { obj = c; invokeReturning(c.getFoo("foo", false), "bas"); } }; assert "bas".equals(obj.getFoo("foo", false)); Expectations.assertSatisfied(); } public static class MyClass { public String getFoo(String str, boolean bool) { if (bool) { return "foo"; } else { return "bar"; } } } } 

缺点是它需要Java 5/6。

您还可以看看使用Groovy进行的testing。 在Groovy中,您可以使用'as'运算符轻松地模拟Java接口:

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

除了这个基本的function外,Groovy在嘲笑方面还提供了很多,包括强大的MockForStubFor类。

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

我开始使用EasyMock模拟 。 足够容易理解,但重播步骤有点烦人。 Mockito删除了这个,也有一个更清晰的语法,因为它看起来像可读性是它的主要目标之一。 我不能强调这是多么重要,因为大多数开发人员会花时间阅读和维护现有的代码,而不是创build它。

另一个好处是,接口和实现类以相同的方式处理,不像EasyMock那样,您仍然需要记住(并检查)使用EasyMock类扩展。

我最近浏览了一下JMockit ,虽然function清单非常全面,但我认为这样做的代价是代码易读,而且必须编写更多代码。

对我来说,Mockito击中甜蜜的地方,很容易写和阅读,并处理大多数代码将需要的情况。 与PowerMock使用Mockito将是我的select。

需要考虑的一件事情是,如果你自己开发,或者组织紧密的团队,那么你select的工具可能不是最好的select,因为拥有不同技能水平的开发人员可能会遇到这样的问题。 在后一种情况下,可读性,易用性和简单性需要更多的考虑。 如果许多人最终不使用或不维护testing,那么没有意义获得最终的嘲讽框架。

我们在工作中大量使用EasyMock和EasyMock Class Extension,并且非常满意。 它基本上给你你需要的一切。 看看文档,有一个非常好的例子,它显示了EasyMock的所有function。

我早期使用JMock。 我在最后一个项目中尝试过Mockito,并且很喜欢它。 更简洁,更清洁。 PowerMock涵盖了Mockito中不存在的所有需求,例如嘲笑静态代码,嘲笑实例创build,嘲笑最终的类和方法。 所以我有我需要做的所有工作。

我喜欢JMock,因为你可以设定预期。 这与检查是否在某些模拟库中find方法是完全不同的。 使用JMock,你可以写出非常复杂的期望。 看看jmock的骗子 。

是的,Mockito是一个很好的框架。 我和hamcrest和Google guice一起使用它来设置我的testing。

嘲笑的最佳解决scheme是使机器完成所有使用基于规格的自动化testing的工作。 对于Java,请参阅Functional Java库中包含的ScalaCheck和Reductio框架。 使用基于规范的自动化testing框架,您可以提供被testing方法的规范(关于它的属性应该是真实的),框架自动生成testing以及模拟对象。

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

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

当你调用propSqrt.check() ,ScalaCheck会生成数百个整数并检查你的属性,同时自动确保边框被覆盖。

尽pipeScalaCheck是用Scala编写的,并且需要Scala编译器,但使用它testingJava代码是很容易的。 Functional Java中的Reductio框架是相同概念的纯Java实现。

Mockito还提供了stubbing方法,匹配参数(如anyInt()和anyString())的选项,validation调用次数(times(3),atLeastOnce(),never()) 等等 。

我也发现Mockito 简单而干净 。

我不喜欢Mockito的一件事就是你不能存储静态方法 。

对于稍有不同的东西,您可以使用JRuby和Mocha ,它们结合在JtestR中 ,为您的Java代码编写testing,并使用简洁明了的Ruby。 这里有一些有用的嘲讽示例。 这种方法的一个优点是嘲笑具体的类是非常简单的。

我开始通过JMock使用模拟,但最终转换到使用EasyMock。 EasyMock就是这样,而且提供了一种更自然的语法。 我从此没有转换。