我应该如何模拟我要测试的对象中的单个方法?

How should I mock out a single method inside an object I'm trying to test?

我有一个 class 的问题,我正在测试几乎每个我想测试的方法,每个方法做的第一件事就是调用这个特定的方法。所有这些其他方法调用一次的这个方法需要很长时间才能执行。我不想每次 运行 我的测试都需要等待,这真的是浪费时间。

我尝试使用 Mocktio @Spy 方法,但我 运行 遇到了问题,因为非常长的方法没有 return 任何东西。有人可以建议一种在我正在尝试测试的 class 中模拟单个方法的好方法吗?


示例:

public class myClass {

    public void methodOne() {
        reallyLongMethod();
        // More code
    }

    public void methodTwo() {
        reallyLongMethod();
        // More code
    }

    .
    .
    .

    public void methodN() {
        reallyLongMethod();
        // More code
    }

    public void reallyLongMethod() {

    }
}

这是我要测试的class。我想测试所有 'methodX()' 方法。但是,我不想 运行 reallyLongMethod 每一次。

那么,有没有办法使用 Mockito 'Spy' 来 stub out reallyLongMethod()?尽管它什么都没有return?

您可以在 doNothing() 中使用间谍,但请确保在测试期间使用间谍。 Mockito 间谍复制原件,而不是委托给它。

@RunWith(MockitoJUnitRunner.class)
public class YourTest {
  // Option 1:
  // @Spy MyClass myClass = new MyClass();

  // Option 2 (see @Before method)
  MyClass myClass;

  @Before public void ignoreReallyLongMethod() {
    myClass = spy(new MyClass());  // discard original
    doNothing().when(myClass).reallyLongMethod();
  }

  @Test public void methodOneWorks() {
    myClass.methodOne();  // you're using the spy here
    assertEquals(42, myClass.getFoo());
  }
}

虽然这确实会产生代码味道,但不要在测试class 下模拟或存根 ,只要您仔细测试方法行为(methodOne) 而不是存根行为 (reallyLongMethod) 你会很高兴的。如果您确实想测试 reallyLongMethod,则需要使用不同的对象实例,否则您将 "test" 单独调用 doNothing()。请记住,如果 reallyLongMethod 和您的其他方法有任何 负面影响 ,这些测试不会告诉您。


顺便说一句,您也可以在不使用 Mockito 的情况下执行等效操作,这可能会让您更清楚地了解您在使用模拟做什么或不做什么:

@RunWith(JUnit4.class)
public class YourTest {
  MyClass myClass;

  @Before public void createMyClass() {
    myClass = new MyClass() {  // create an anonymous inner class
      @Override public void reallyLongMethod() {}  // that does nothing here
    };
  }
}