Java的最佳模拟框架是什么?

时间:2020-03-05 18:42:05  来源:igfitidea点击:

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

解决方案

回答

我使用Mockito取得了成功。

当我尝试学习JMock和EasyMock时,我发现学习曲线有些陡峭(尽管可能仅仅是我一个人)。

我喜欢Mockito,因为它的语法简洁明了,我很快就能掌握。最小的语法旨在很好地支持常见情况,尽管我几次需要做更复杂的事情,但我发现我想要的东西是受支持的并且易于理解。

这是Mockito主页上的一个(删节后的)示例:

import static org.mockito.Mockito.*;

List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();

没有比这更简单的了。

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

回答

我们在工作中大量使用EasyMock和EasyMock类扩展,对此感到非常满意。它基本上可以为我们提供所需的一切。看一下文档,有一个非常好的示例,向我们展示了EasyMock的所有功能。

回答

我开始通过JMock使用模拟,但最终过渡为使用EasyMock。 EasyMock就是这样,-更轻松-并且提供了一种感觉更自然的语法。从那以后我再也没有切换。

回答

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

我还发现Mockito简单干净。

我不喜欢Mockito的一件事是我们不能对静态方法进行存根。

回答

是的,Mockito是一个很好的框架。我将其与hamcrest和Google guice结合使用来设置测试。

回答

我们也可以看看使用Groovy进行测试。在Groovy中,我们可以使用'as'运算符轻松模拟Java接口:

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

除了此基本功能之外,Groovy在模拟方面还提供了更多功能,包括强大的MockForStubFor类。

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

回答

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

回答

我喜欢JMock,因为我们能够设定期望。这与检查是否在某些模拟库中找到了一种方法完全不同。使用JMock可以编写非常复杂的期望。见jmock作弊作弊。

回答

我是PowerMock的创建者,因此显然我必须建议这样做! :-)

PowerMock扩展了EasyMock和Mockito的功能,能够模拟静态方法,最终方法甚至私有方法。 EasyMock支持已完成,但是Mockito插件需要更多工作。我们还计划增加对JMock的支持。

PowerMock并不是要替换其他框架,而是可以在其他框架不允许模拟的棘手情况下使用。 PowerMock还包含其他有用的功能,例如禁止使用静态初始化程序和构造函数。

回答

最好的模拟解决方案是让机器通过基于规范的自动化测试来完成所有工作。对于Java,请参阅ScalaCheck和Functional 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代码还是很容易的。 Functional Java中的Reductio框架是相同概念的纯Java实现。

回答

如果有所不同,则可以使用JtestR中结合使用的JRuby和Mocha,以表现力和简洁的Ruby编写Java代码测试。这里有一些有用的JtestR模拟示例。这种方法的一个优点是模拟具体类非常简单。

回答

JMockit项目站点包含有关当前模拟工具包的大量比较信息。

特别是,请查看功能比较矩阵,其中包括EasyMock,jMock,Mockito,Unitils Mock,PowerMock,当然还有JMockit。我会尽量保持其准确性和最新性。

回答

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