关于单元测试:什么是最好的Java模拟框架?

关于单元测试:什么是最好的Java模拟框架?

What's the best mock framework for Java?

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


我使用Mockito取得了很大的成功。

当我尝试学习JMock和EasyMock时,我发现学习曲线有点陡峭(尽管这可能只是我)。

我喜欢Mockito,因为它简单而干净的语法让我能够很快掌握。最小的语法旨在很好地支持常见的情况,虽然我需要做一些更复杂的事情我发现我想要的东西是支持和易于掌握的。

这是Mockito主页上的一个(删节)示例:

1
2
3
4
5
import static org.mockito.Mockito.*;

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

它没有那么简单。

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


我是PowerMock的创造者所以显然我必须推荐它! :-)

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

PowerMock并不打算替换其他框架,而是可以在其他框架不允许模拟的棘手情况下使用它。 PowerMock还包含其他有用的功能,例如抑制静态初始化器和构造器。


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

特别是,查看功能比较矩阵,其中包括EasyMock,jMock,Mockito,Unitils Mock,PowerMock,当然还有JMockit。我尽可能地保持其准确和最新。


我在JMockit上取得了成功。

这是非常新的,因此它有点原始且记录不足。它使用ASM动态重新定义类字节码,因此它可以模拟所有方法,包括静态,私有,构造函数和静态初始化器。例如:

1
2
3
4
5
6
7
8
9
10
11
12
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接口,允许记录/播放场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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查看测试。在Groovy中,您可以使用'as'运算符轻松模拟Java接口:

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

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

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


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

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

我最近快速浏览了JMockit,虽然功能的清单非常全面,但我认为这样做的代价是结果代码的易读性,并且必须写更多内容。

对我来说,Mockito击中了最佳位置,易于编写和阅读,并处理大多数代码所需的大多数情况。使用Mockito和PowerMock将是我的选择。

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


我们在工作中大量使用EasyMock和EasyMock Class Extension,并对它非常满意。它基本上为您提供所需的一切。看看文档,这是一个非常好的例子,它向您展示了EasyMock的所有功能。


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


我喜欢JMock因为你能够设定期望。这与检查是否在某些模拟库中调用方法完全不同。使用JMock,您可以编写非常复杂的期望。看到j??mock作弊。


是的,Mockito是一个很棒的框架。我和hamcrest以及Google guice一起使用它来设置我的测试。


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

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

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

当您调用propSqrt.check()时,ScalaCheck会生成数百个整数并检查每个整数的属性,同时自动确保边缘情况得到很好的覆盖。

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


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

我还发现Mockito简单干净。

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


对于稍微不同的东西,你可以使用JRuby和Mocha结合在JtestR中,用富有表现力和简洁的Ruby编写Java代码测试。这里有一些与JtestR有用的模拟示例。这种方法的一个优点是模拟具体类非常简单。


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


推荐阅读

    miui模拟器电脑版|MIUI模拟器

    miui模拟器电脑版|MIUI模拟器,,1. MIUI模拟器笔记本电脑没有办法刷MIUI系统。MIUI系统是小米为手机研发的,基于安卓系统的手机用系统,笔记本

    拍拍模拟器电脑版|拍拍猴模拟器

    拍拍模拟器电脑版|拍拍猴模拟器,,1. 拍拍猴模拟器爬猴,5173,淘宝,拍拍,慧聪,易宝,送宝挺多的!我比较信任爬猴的 2. 拍拍拍模拟器游戏ppsspp还是相

    模拟器设置vt|模拟器设置VT

    模拟器设置vt|模拟器设置VT,,模拟器设置vtwin7安卓模拟器vt开启步骤如下:1.开启VT需要进入BOIS进行设置。首先重启电脑,在电脑启动时不停地

    Python之可迭代对象、迭代器、生成器

    Python之可迭代对象、迭代器、生成器,迭代,生成器,一、概念描述可迭代对象就是可以迭代的对象,我们可以通过内置的iter函数获取其迭代器,可

    应用程序对象

    应用程序对象,,应用程序对象是一个应用程序级对象,用于在所有用户之间共享信息,并且在Web应用程序运行期间可以保存数据。 应用的性质: 方法