Java 最好的模拟框架是什么?[关闭]
-
09-06-2019 - |
题
在 Java 中创建模拟对象的最佳框架是什么?为什么?每个框架的优点和缺点是什么?
解决方案
我使用它取得了很好的成功 莫基托.
当我尝试学习 JMock 和 EasyMock 时,我发现学习曲线有点陡峭(尽管也许只有我这么认为)。
我喜欢 Mockito,因为它的语法简单明了,我能够很快掌握。最小的语法旨在很好地支持常见情况,尽管有几次我需要做一些更复杂的事情,但我发现我想要的东西得到了支持并且易于掌握。
这是 Mockito 主页上的一个(删节的)示例:
import static org.mockito.Mockito.*;
List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();
没有比这更简单的了。
我能想到的唯一主要缺点是它不会模拟静态方法。
其他提示
这 JMockit 项目站点 包含当前模拟工具包的大量比较信息。
特别是,请查看 特征比较矩阵, ,其中涵盖 EasyMock、jMock、Mockito、Unitils Mock、PowerMock,当然还有 JMockit。我尽力保持其准确性和最新性。
我已经取得了成功 JMockit.
它是相当新的,所以有点原始并且记录不足。它用 先进制造商 动态地重新定义类字节码,因此它可以模拟所有方法,包括静态、私有、构造函数和静态初始值设定项。例如:
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 接口,也允许记录/回放场景:
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 接口:
def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest
除了这个基本功能之外,Groovy 在模拟方面还提供了更多功能,包括强大的 MockFor
和 StubFor
类。
我开始使用模拟 易模拟. 。很容易理解,但重播步骤有点烦人。 莫基托 删除了这一点,还有一个更清晰的语法,因为看起来可读性是其主要目标之一。我无法充分强调这一点的重要性,因为大多数开发人员都会花时间阅读和维护现有代码,而不是创建代码。
另一个好处是接口和实现类以相同的方式处理,这与 EasyMock 不同,在 EasyMock 中您仍然需要记住(并检查)以使用 EasyMock 类扩展。
我快速浏览了一下 JMockit 最近,虽然功能清单相当全面,但我认为这样做的代价是结果代码的易读性,并且必须编写更多代码。
对我来说,Mockito 达到了最佳点,易于编写和阅读,并且可以处理大多数代码所需的大多数情况。使用 莫基托 和 电源模拟 将是我的选择。
需要考虑的一件事是,如果您自己开发或在一个紧密的小型团队中进行开发,那么您选择的工具对于拥有不同技能水平的开发人员的大公司来说可能不是最好的选择。在后一种情况下,需要更多考虑可读性、易用性和简单性。如果很多人最终不使用它或不维护测试,那么获得最终的模拟框架就没有意义。
我们大量使用 易模拟 和 EasyMock 类扩展正在工作,并且对此非常满意。它基本上为您提供了您需要的一切。看一下文档,有一个非常好的示例,向您展示了 EasyMock 的所有功能。
我很早就用过JMock。我在上一个项目中尝试过 Mockito 并且喜欢它。更简洁,更干净。PowerMock 涵盖了 Mockito 中没有的所有需求,例如模拟静态代码、模拟实例创建、模拟最终类和方法。所以我拥有完成工作所需的一切。
我喜欢 JMock 因为你能够设定期望。这与检查某些模拟库中是否调用了方法完全不同。使用 JMock,您可以编写非常复杂的期望。查看jmock 作弊.
模拟的最佳解决方案是让机器通过基于规范的自动化测试来完成所有工作。对于 Java,请参阅 Scala检查 和 还原 框架包含在 函数式Java 图书馆。使用基于规范的自动化测试框架,您可以提供被测方法的规范(有关该方法的属性应该为真),并且框架会自动生成测试和模拟对象。
例如,以下属性测试 Math.sqrt 方法以查看任何正数 n 的平方的平方根是否等于 n。
val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }
你打电话时 propSqrt.check()
, ,ScalaCheck 生成数百个整数并检查每个整数的属性,同时自动确保边缘情况得到很好的覆盖。
尽管 ScalaCheck 是用 Scala 编写的,并且需要 Scala 编译器,但使用它测试 Java 代码很容易。Function Java 中的 Reductio 框架是相同概念的纯 Java 实现。
我开始通过 JMock 使用模拟,但最终过渡到使用 EasyMock。EasyMock 就是这样——更简单——并且提供了一种感觉更自然的语法。从那以后我就没有换过。