用Java创建模拟对象的最佳框架是什么?为什么?每个框架的优点和缺点是什么?
当前回答
我已经成功地使用了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的一点是你不能存根静态方法。
对于一些不同的东西,您可以使用JtestR中组合的JRuby和Mocha,以表达性和简洁的Ruby为您的Java代码编写测试。这里有一些有用的JtestR模拟示例。这种方法的一个优点是模拟具体类非常简单。
我开始使用EasyMock模拟。很容易理解,但重放步骤有点烦人。Mockito删除了这一点,也有一个更清晰的语法,因为可读性似乎是它的主要目标之一。我再怎么强调这一点也不为过,因为大多数开发人员会花时间阅读和维护现有代码,而不是创建它。
另一个好处是接口和实现类以相同的方式处理,不像在EasyMock中,您仍然需要记住(并检查)使用EasyMock类扩展。
我最近快速浏览了一下JMockit,虽然它的特性清单非常全面,但我认为这样做的代价是代码的易读性,并且必须编写更多的代码。
对我来说,Mockito达到了最佳的位置,易于编写和阅读,并处理大多数代码所需要的大多数情况。使用Mockito和PowerMock将是我的选择。
需要考虑的一件事是,如果您是独自开发,或者在一个小型紧密的团队中开发,那么对于拥有不同技能水平的开发人员的大公司来说,您所选择的工具可能不是最佳选择。对于后一种情况,需要更多地考虑可读性、易用性和简洁性。如果许多人最终不使用或不维护测试,那么获得最终的mock框架是没有意义的。
我喜欢JMock,因为您能够设置期望。这与检查在某些模拟库中是否调用了某个方法完全不同。使用JMock可以编写非常复杂的期望。看那个jmock骗子。
我是PowerMock的创建者,所以显然我必须推荐它!: -)
PowerMock扩展了EasyMock和Mockito,具有模拟静态方法、final方法甚至私有方法的能力。EasyMock支持已经完成,但是Mockito插件还需要一些工作。我们还计划添加JMock支持。
PowerMock并不打算取代其他框架,而是可以在其他框架不允许模拟的复杂情况下使用它。PowerMock还包含其他有用的特性,例如抑制静态初始化器和构造函数。
推荐文章
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Java生成两个给定值之间的随机数
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 比较JUnit断言中的数组,简洁的内置方式?
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- 如何直接从测试驱动程序调用自定义的Django manage.py命令?
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- 如何重置笑话模拟函数调用计数之前,每次测试
- Java 8流和数组操作