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


当前回答

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

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

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

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

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

其他回答

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

是的,Mockito是一个很棒的框架。我使用它与hamcrest和谷歌guice一起设置我的测试。

我已经成功地使用了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...
}

它有一个期望界面,允许记录/回放场景以及:

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。

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

我还发现Mockito简单干净。

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

我开始通过JMock使用mock,但最终过渡到使用EasyMock。EasyMock就是这样——更简单——并提供了一种感觉更自然的语法。从那以后我就没换过。