我正在研究在我的项目中使用哪个 Mocking 框架,并将范围缩小到 JMockit和 莫基托。
我注意到,在 Stackoverflow 上,莫基托被选为“ Java 最好的模拟框架”。 在比较 JMockit的“ 模具比较矩阵”的功能,它似乎是 JMockit有多个不同的功能。
是否有任何人有任何具体的信息(不是意见)对什么 莫基托可以做,不能实现与 JMockit反之亦然?
我个人更喜欢 EasyMock。 在漂亮、正常和严格的模仿控件之间转换的能力是我最喜欢的特性之一。
为了方便地测试我们的遗留代码库(使用大量静态方法调用等) ,JMockit 非常有价值。[无耻的 文章插头在我的博客上]
我之所以使用 jMockit 只有,是因为它是在 Depacktation.class 中的反射库。我实际上很喜欢 Mockito 的风格,但是我拒绝改变我的代码并且混淆我的 API,只是为了让一个有限的测试框架能够得到它。我喜欢测试我所有的代码,所以一个不能轻松测试私有方法的框架不是我想要使用的。
我被 这篇文章动摇了
经过一段(不可否认的巨大)学习曲线之后,jMockit 现在是我用于模拟的主要单元测试框架。
更新于2019年9月: 唯一的 SpringBoot 支持(默认情况下)模拟框架是 译自: 美国《科学》杂志网站(https://site.modito.org/rel = “ noReferrer”> Mockito)。如果你使用 Spring,答案是显而易见的。
我认为竞争是在 JMockit和 PowerMock之间,然后是 莫基托。
我会留下“普通的”jMock 和 EasyMock,因为它们只使用代理和 CGLIB,而不像较新的框架那样使用 Java5插装。
JMock 也没有一个稳定的发布超过4年。JMock 2.6.0从 RC1到 RC2需要两年的时间,然后又过了两年才真正发布。
关于代理和 CGLIB 对仪器:
(EasyMock 和 jMock)是基于 java.lang.response. Proxy, 它需要一个接口 除此之外,这些措施 支持模拟对象的创建 通过 CGLIB 子类的类 因为这一点,说 类不能是最终的,也不能是唯一的 可重写的实例方法可以是 最重要的是, 当使用这些工具时 测试代码的依赖项(即 上的其他类的对象 测试中的给定类 (视乎情况而定)必须由 测试,以便模拟实例可以是 传递给那些客户 因此,依赖 不能简单地用 客户端类中的新运算符 我们要编写单元测试。 最终,技术上的局限性 传统模仿工具的强加 下列设计限制 生产代码: 测试中可能需要模拟的每个类都必须实现 一个单独的接口或不是最终的。 必须获取要测试的每个类的依赖项 通过可配置的实例创建 方法(工厂或服务) 定位符) ,或者为依赖项而暴露 注入。否则,单元测试不会 能够通过模拟实现 下的单位的受养人数目 测试。 因为只能模拟实例方法,所以要对类进行单元测试 不能调用任何静态方法 它们的依赖关系,也不实例化 它们使用任何构造函数。
(EasyMock 和 jMock)是基于 java.lang.response. Proxy, 它需要一个接口 除此之外,这些措施 支持模拟对象的创建 通过 CGLIB 子类的类 因为这一点,说 类不能是最终的,也不能是唯一的 可重写的实例方法可以是 最重要的是, 当使用这些工具时 测试代码的依赖项(即 上的其他类的对象 测试中的给定类 (视乎情况而定)必须由 测试,以便模拟实例可以是 传递给那些客户 因此,依赖 不能简单地用 客户端类中的新运算符 我们要编写单元测试。
最终,技术上的局限性 传统模仿工具的强加 下列设计限制 生产代码:
上面的内容是从 http://jmockit.org/about.html中复制过来的,而且,它还通过几种方式比较了它自己(JMockit)、 PowerMock 和 Mockito:
现在有了其他的模仿工具 Java 也克服了 传统方法的局限性, PowerMock jEasyTest 和 模拟注射,最接近的那个 JMockit 的特性集是 PowerMock,因此我将简要评估 它在这里(另外两个在这里) 更有限,而且似乎没有 积极发展)。 JMockit vs PowerMock 首先,PowerMock 没有提供一个完整的模拟 API, 而是作为 另一个工具,目前可以 EasyMock 或者 Mockito 很明显 现有用户的优势 那些工具。 另一方面,JMockit 提供了全新的 API,尽管 它的主要 API (期望值)是类似的 和 jMock 创造一个更长的学习曲线,它 还允许 JMockit 提供一个 更简单,更一致,更容易 使用 API。 与 JMockit 期望 API 相比,PowerMock API 是 更多的“低水平”,迫使用户 找出并指定哪些类 需要为测试作好准备 @ PrepareForTest ({ ClassA.class, ... })注释)和要求 要处理的特定 API 调用 各种各样的语言结构 可能出现在制作中 代码: 静态方法 (仿静电(ClassA.class)), 构造函数 (抑制(构造函数(ClassXyz.class)) , 构造函数调用 (pectNew (AClass.class)) ,部分 Moks (createPartialMock (ClassX.class, (“ methodToMock”)等等。 使用 JMockit Expections,所有类型的方法和构造函数都是 以一种纯粹陈述性的方式嘲笑, 通过指定的部分嘲弄 中的正则表达式 或者简单地“不嘲弄” 没有记录的成员 期望; 也就是说,开发人员 只是简单地声明一些共享的“ mock” 字段,或者一些 “本地模拟字段”和/或“模拟 个别测试的参数 方法(在最后一种情况下,是 @ 嘲笑的注释通常不会 需要)。 JMockit 中提供的一些功能,比如对 Mockit 的支持 Equals 和 hashCode,重写 方法,以及其他方法,目前没有 PowerMock 支持 没有相当于 JMockit 的能力 捕捉实例和模拟 指定基数的实现 在测试执行时输入,而不使用 测试代码本身具有任何 实际执行的知识 课程。 PowerMock 使用自定义类加载器(通常每个测试类一个) 以便生成修改后的版本 被嘲笑的阶级。如此沉重的使用 自定义类加载器的数量可能导致 与第三方图书馆发生冲突, 因此有时需要使用 @ PowerMockIgnore (“ package.to.be.Ignore”) 测试类的注释。 JMockit (通过 “ Java 代理”)更简单、更安全, 虽然它确实需要传递 时将“-javaagent”参数设置为 JVM 在 JDK 1.5上开发; 在 JDK 1.6 + 上开发 (总是可以用来 开发,即使部署在 旧版本)没有这种说法 需求,因为 JMockit 可以 透明地加载 Java 代理 通过使用附加 API 请求。 最近的另一个嘲笑工具是 莫基托。虽然它没有尝试 克服老年人的局限性 工具(jMock,EasyMock) ,它可以 引进一种新的行为方式 使用 Mockit 进行测试 支持这种另类风格, 通过验证 API。 JMockit 对 Mockito Mockito 依靠对其 API 的显式调用来分离代码 在记录(时间)和 核实(...)阶段 意味着对模拟的任何调用 测试代码中的对象也需要 对 Mocking API 的调用。 此外,这通常会导致 当(...)和 验证(模拟) ... 电话。 对于 JMockit,不存在类似的调用 NonStrictExpections ()和 new 验证()构造函数调用,但是 每次测试只出现一次 (典型地) ,而且完全是 独立于对... 的调用 模拟方法和构造函数。 Mockito API 在用于 对模拟方法的调用 在录音阶段,我们有 当(嘲笑。模仿方法(Args)) 在验证阶段这个相同的调用 将被写成 验证(模拟)。 注意,在第一种情况下 调用嘲弄方法 直接在模拟对象上,而在 第二种情况是在 通过验证(模拟)返回的对象。 JMockit 没有这样的不一致性,因为对 总是使用模拟方法 直接在模拟实例上 (只有一个例外: 来匹配对同一 模拟实例,一个 onInstance (模拟) 调用,导致类似于 模拟方法(args) ; 大多数测试都不需要用到这个, 不过。) 就像其他依赖于方法的模仿工具一样 锁链/包装,Mockito 也运行 转换成不一致的语法 Void 方法。例如,你写 然后抛出(新的) RuntimeException () ; 用于非空的 方法和 doThrow (新的 RuntimeException ()) . when (mockedList) . clear () ; 对于一个无效的。与 JMockit,它是 总是相同的语法: Clear () ; result = new 运行时异常() ; 。 在使用 Mockito 间谍方面还有另一个矛盾之处: “模仿” 让真正的方法 在间谍实例上执行 例如,如果 spit 指的是一个空的 列表,然后代替写 当(spy.get (0))。然后返回(“ foo”)你 将需要写 返回(“ foo”)。当(间谍) JMockit,动态模拟特性 提供类似的功能 间谍,但从那以后就没有这个问题了 真正的方法只在 重播阶段。 在 EasyMock 和 jMock (Java 的第一个 Mocking API)中,关注的焦点是 完全依靠预期的记录 模拟方法的调用 模拟对象(默认情况下)没有 允许意外的调用。那些 API 还提供 允许调用模拟对象 允许意想不到的调用, 但这被当作二等车 除此之外,还有这些 工具没有办法显式地 方法之后验证对模拟的调用 测试中的代码已被执行 验证是隐式执行的 而且是自动的。 在 Mockito (以及 UnitilsMock)中,相反的观点是 所有模拟对象的调用 可能会发生在测试期间, 不论是否录音, 出乎意料,核实是 显式地在代码之后执行 被测试的,从来没有 自然而然地。 这两种方法都太极端了,因此不是最优的。 JMockit 期望与验证 是唯一允许 开发人员可以无缝地选择 严格(预期)的最佳组合 默认情况下)和非严格(由 默认值) 测试。 更明确地说,Mockito API 有以下缺点 需要验证对 非空腔模拟方法发生在 测试,但测试需要一个 返回值 属性的默认值不同 返回类型,然后是 Mockito 测试 将有重复的代码: a 然后返回(xyz) 在记录阶段调用,并且 中验证(模拟) 使用 JMockit,一个严格的 期望总是可以被记录下来, 不需要很明确 或者,调用 计数约束(乘以1)可以是 指定的任何记录非严格 期望(与莫基托这样 约束只能在 验证(模拟、约束)调用。 Mockito 对于有序和完整的验证的语法很差 核实(即核对 对模拟对象的所有调用都是 明确验证) 大小写的情况下,额外的对象需要是 创建,并调用 它: InOrder inOrder = inOrder (仿1, 在第二种情况下,调用 如 verifyNoMoreInteractions (mock)或 验证零交互(仿真1,仿真2) 需要被制造出来。 使用 JMockit,只需编写 new VerificationsInOrder ()或 new ()代替新的 验证()(或新的) 要组合的 FullVerificationsInOrder () 无须详细说明 包含哪些模拟对象 额外的嘲讽 API 调用 奖金,通过打电话 中的调用() 有序的验证块,你可以 执行与订单有关的验证 这在 Mockito 根本不可能。 最后是 JMockit 测试工具包 拥有一个更有野心的 扩大范围和 目标 比其他模拟工具包,在 提供完整及 复杂的开发者测试 甚至是一个很好的用于模拟的 API 没有人为的限制,不是 足以生产出 测试。一个 IDE 不可知,易于使用, 和良好的集成代码覆盖工具 也是必不可少的,这就是为什么 JMockit Coverage 旨在提供。 开发人员测试的另一部分 工具集将变得更加有用 随着测试套件规模的增长, 增量重新运行测试的能力 在本地化生产之后 代码; 这也包含在 覆盖工具。
现在有了其他的模仿工具 Java 也克服了 传统方法的局限性, PowerMock jEasyTest 和 模拟注射,最接近的那个 JMockit 的特性集是 PowerMock,因此我将简要评估 它在这里(另外两个在这里) 更有限,而且似乎没有 积极发展)。
最近的另一个嘲笑工具是 莫基托。虽然它没有尝试 克服老年人的局限性 工具(jMock,EasyMock) ,它可以 引进一种新的行为方式 使用 Mockit 进行测试 支持这种另类风格, 通过验证 API。
最后是 JMockit 测试工具包 拥有一个更有野心的 扩大范围和 目标 比其他模拟工具包,在 提供完整及 复杂的开发者测试 甚至是一个很好的用于模拟的 API 没有人为的限制,不是 足以生产出 测试。一个 IDE 不可知,易于使用, 和良好的集成代码覆盖工具 也是必不可少的,这就是为什么 JMockit Coverage 旨在提供。 开发人员测试的另一部分 工具集将变得更加有用 随着测试套件规模的增长, 增量重新运行测试的能力 在本地化生产之后 代码; 这也包含在 覆盖工具。
(当然,消息来源可能有偏见,但是...)
我觉得应该用 JMockit。它是最容易使用的,灵活的,并且适用于几乎所有的情况,甚至当你不能控制要测试的类(或者由于兼容性等原因你不能破坏它)的困难的情况和场景。
我在 JMockit 的经历是非常积极的。
我曾与 Mockito 和 JMockit 共事过,我与他们共事的经历是:
莫基托:
EasyMock:
JMockit:
此外,JMockit 的其他好处:
我个人更喜欢 JMockit,我认为它的特性更丰富、更灵活,但需要更陡峭的学习曲线。通常有多种方法可以实现相同的模拟效果,在设计模拟时需要更加小心。