JUnit使用Mockito、EasyMock等进行模拟测试

4
我将尝试模拟我正在测试的类中对象的方法。例如:
class ClassToTest {
   public doSomething () {
       SomeObject a = new SomeObject ();
       a.doSomethingElse ();
   }
}

有没有一种方法可以模拟变量"a"的方法?我希望在测试期间doSomethingElse什么都不做。我目前正在使用Mockito,但我也可以接受任何模拟框架。
谢谢
6个回答

2

是的,有一种方法可以通过以下JMockit测试来展示:

public void testDoSomething(final SomeObject mock)
{
    new ClassToTest().doSomething();

    new Verifications() {{ mock.doSomethingElse(); }};
}

无需重构测试代码以使用包装器、DI等;只需模拟您需要模拟的内容即可。

2
当然,通过一些重构是可以实现的:
class SomeObject {
    public void doSomethingElse()
    {

    }
}

class ClassToTest
{
    private final SomeObject someObject;

    public void doSomething()
    {
        someObject.doSomethingElse();
    }

    public ClassToTest(SomeObject someObject)
    {
        this.someObject = someObject;
    }
}

class Test {
    @Test
    public void testDoSomething()
    {
        SomeObject someObject = Mockito.mock(SomeObject.class);
        new ClassToTest(someObject).doSomething();
        Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse();
    }
}

1
是的,这也是我的想法。我只是不确定是否可以(现在)模拟本地变量。 - Shaun

2

当引用变量"a"被声明为局部变量时,例如在您的情况下,无法模拟它。您可以考虑将依赖项注入到SomeObject中,例如作为doSomething方法的参数。这样,在测试中,您可以注入SomeObject的模拟。

依赖注入的好处之一是增强可测试性


1

我相信你可以在EasyMock 2.5或更早的版本中使用EasyMock Class Extensions,而且显然它已经包含在3.0中了。请参阅上一页的这部分内容以获取有关您正在尝试执行的操作的信息。话虽如此,我个人并没有尝试过这样做,所以我不知道它会运行得有多好。


使用EasyMock类扩展,您可以模拟只能模拟接口而无需类扩展的类。然而,您无法模拟声明为局部变量的引用。 - Jeroen Rosenberg

0
如果您想在每次调用时获得一个新的实例,我建议按以下方式进行重构:
class ClassToTest {
   public doSomething () {
      SomeObject a = getInstance();
      a.doSomethingElse ();
   }
   protected SomeObject getInstance() {
      return new SomeObject();
   }
}

然后,您可以创建一个扩展ClassToTest的测试类,覆盖getInstance()方法,并提供一个模拟对象。

当然,这只有在您愿意公开getInstance()方法时才可行,因此如果该类是公共API的一部分,则不建议使用此方法。如果是这种情况,请考虑使用依赖注入提供工厂类。


如果您选择这条路,我认为我会创建一个提供程序(工厂)并注入它。像Guice这样的良好DI框架将为您创建工厂。 - Michael Lloyd Lee mlk

0
class ClassToTest {
    private SomethingElseInterface somethingElseDoer ;

    public ClassToTest(SomethingElseInterface somethingElseDoer) {
        this.somethingElseDoer = somethingElseDoer;
    }

    public doSomething () {
        somethingElseDoer.doSomethingElse();
    }
}

你在哪里使用它:

SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it
ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor
foo.doSomething();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接