4

我试图在我正在测试的类中模拟一个对象的方法。

例如

class ClassToTest {
   public doSomething () {
       SomeObject a = new SomeObject ();
       a.doSomethingElse ();
   }
}

有没有办法模拟变量“a”的方法?我希望 doSomethingElse 在测试期间什么都不做。我目前正在使用 Mockito,但我对任何模拟框架持开放态度。

谢谢

4

6 回答 6

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();
    }
}
于 2010-10-14T13:02:49.663 回答
2

是的,有一种方法,如下面的JMockit测试所示:

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

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

无需重构被测代码以使用包装器、DI 等;简单地嘲笑任何你需要被嘲笑的东西。

于 2011-02-15T12:26:46.343 回答
2

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

依赖注入的好处之一是增加了可测试性。

于 2010-10-14T12:56:53.853 回答
1

我相信您可以使用EasyMock 2.5 或更早版本的 EasyMock 类扩展,并且显然它包含在 3.0 中。有关您尝试执行的操作的信息,请参阅上一页的这一部分。也就是说,我个人并没有尝试过这样做,所以我不知道它的效果如何。

于 2010-10-14T12:59:23.363 回答
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();
于 2010-10-14T13:36:18.610 回答
0

如果您希望在每次调用中都有一个新实例,我建议您通过以下方式进行重构:

class ClassToTest {
   public doSomething () {
      SomeObject a = getInstance();
      a.doSomethingElse ();
   }
   protected SomeObject getInstance() {
      return new SomeObject();
   }
}

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

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

于 2010-10-14T13:14:32.587 回答