【问题标题】:What's the best mock framework for Java? [closed]Java 最好的模拟框架是什么? [关闭]
【发布时间】:2010-09-06 13:36:03
【问题描述】:

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

【问题讨论】:

    标签: java unit-testing mocking


    【解决方案1】:

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

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

    我喜欢 Mockito,因为它的语法简单明了,我能够很快掌握。最小语法旨在很好地支持常见情况,尽管有几次我需要做一些更复杂的事情,但我发现我想要的东西得到了支持并且很容易掌握。

    这是来自 Mockito 主页的(删节)示例:

    import static org.mockito.Mockito.*;
    
    List mockedList = mock(List.class);
    mockedList.clear();
    verify(mockedList).clear();
    

    没有比这更简单的了。

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

    【讨论】:

    • 美丽。对于静态方法,只需将 Mockito 与 JMockit 结合起来,几乎没有任何类太“遗留”而无法测试。
    • 我喜欢当你尝试做一些你不应该做的事情(例如创建内联模拟)时,你会在异常消息中清楚地解释你做错了什么。
    • 对我来说,绝对。我仍然会无条件地推荐它。当然,如果您发现另一个框架更能满足您的需求,请在另一个答案中提及它,看看它获得了哪些投票以及它获得了哪些类型的 cmets。
    • @MexicanHacker 为什么你不能在 Android 上使用它?我现在正在使用它,与 Robolectric 一起使用。
    • 我正在使用 Mockito 并且喜欢它!很棒的文档(很难找到这种质量的文档,作者做得很好),这对于我们使用东西而不必深入研究框架的代码非常重要!!!
    【解决方案2】:

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

    PowerMock 扩展了 EasyMock 和 Mockito 的能力,具有 mock static methods、最终甚至私有方法的能力。 EasyMock 支持已完成,但 Mockito 插件需要更多工作。我们还计划添加 JMock 支持。

    PowerMock 并非旨在取代其他框架,而是可以在其他框架不允许模拟的棘手情况下使用。 PowerMock 还包含其他有用的功能,例如 suppressing static initializers 和构造函数。

    【讨论】:

    • Powermock 对于在主机 PC 上使用原生 Java 对 Android 应用程序进行单元测试是必不可少的(避免使用慢速模拟器)
    • @Jan 唯一的问题是 PowerMock 在使用 Robolectric 时不兼容 :-( 我想做 @RunWith(PowerMockRunner.class) 和 @RunWith(RobolectricTestRunner.class)
    • 在过去几个月使用 PowerMock 之后,我衷心推荐它!
    • PowerMock 真的很棒。我真的很喜欢静态单例来访问所有内容,这使得测试成为可能。
    • 警告:像模拟 final 方法这样的事情只能在 Powermock 中为 EasyMock 而不是 Mockito。当您不经常使用它时,这有点麻烦。我想知道为什么有些东西不起作用,然后我意识到它只列在 doco 的 Easymock 部分下。
    【解决方案3】:

    JMockit project site 包含大量当前模拟工具包的比较信息。

    特别是查看 feature comparison matrix,它涵盖了 EasyMock、jMock、Mockito、Unitils Mock、PowerMock,当然还有 JMockit。我尽量保持准确和最新。

    【讨论】:

    • JMockit 给我留下了深刻的印象,它的学习曲线更陡峭,但多年来它的文档非常好,它可以模拟任何东西。我从易于学习的 Mockito 开始,但我经常遇到无法用它解决的问题。另一方面,我什至无法想象 JMockit 有什么不可能。
    【解决方案4】:

    我在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...
    }
    

    它还有一个 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。

    【讨论】:

    • 是的,真的可以推荐这个
    • 只是一个更新:JMockit 项目已移至 code.google.com/p/jmockit。自从这篇文章以来,它已经发展了很多(并且仍在发展),现在有大量的文档。
    • JMockit 又搬家了。它现在可以在 Github 上找到。 jmockit.github.io
    【解决方案5】:

    您还可以看看使用 Groovy 进行测试。在 Groovy 中,您可以使用“as”运算符轻松模拟 Java 接口:

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

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

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

    【讨论】:

      【解决方案6】:

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

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

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

      对我来说,Mockito 恰到好处,易于编写和阅读,并且可以处理大多数代码需要的大多数情况。将MockitoPowerMock 一起使用将是我的选择。

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

      【讨论】:

      • +1 这个答案需要更多的支持。人们应该分享他们对框架的真正喜欢或不喜欢的地方。只是“我用过这个……我喜欢它!”是这些好问题在 SO 上被关闭的原因之一。
      【解决方案7】:

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

      【讨论】:

      • 在我的问题中,我更多的是寻找你喜欢和不喜欢模拟框架的地方。我可以找到文档并阅读所有相关内容 - 我想知道使用它的人是怎么想的。
      • EasyMock 仅适用于 Java 5 及更高版本,啊!
      【解决方案8】:

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

      【讨论】:

        【解决方案9】:

        我喜欢 JMock,因为您能够设定期望值。这与检查是否在某些模拟库中找到调用方法完全不同。使用 JMock,您可以编写非常复杂的期望。请参阅 jmock cheat-sheat

        【讨论】:

          【解决方案10】:

          是的,Mockito 是一个很棒的框架。我将它与hamcrestGoogle guice 一起使用来设置我的测试。

          【讨论】:

            【解决方案11】:

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

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

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

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

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

            【讨论】:

              【解决方案12】:

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

              我还发现 Mockito 是 simple and clean

              我不喜欢 Mockito 的一点是你 can't stub static methods

              【讨论】:

              • 这个答案不准确。您不仅限于使用 jMock 的接口。您可以使用 ClassImposteriser 模拟具体类。
              • 你也可以用 EasyMock 做同样的事情。
              • 我已经从我的回答中删除了不准确之处。
              【解决方案13】:

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

              【讨论】:

                【解决方案14】:

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

                【讨论】:

                  猜你喜欢
                  • 2011-01-04
                  • 2010-09-21
                  • 1970-01-01
                  • 2016-12-26
                  • 2010-09-09
                  • 2010-10-22
                  • 2011-03-21
                  • 1970-01-01
                  • 2010-11-13
                  相关资源
                  最近更新 更多