Mockito:验证来自内部匿名类

时间:2017-12-29 02:50:04

标签: java mockito anonymous-class verify method-call

我有一个正在测试的类,它包含一个具有内部匿名类的方法。匿名类中的一个方法从被测试的类中调用一个方法,但Mockito似乎没有意识到这一点。

public class ClassUnderTest {
    Dependency dependency;
    public ClassUnderTest(Dependency d) {
        dependency = d;
    }
    public void method() {
        dependency.returnsObservable().observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io()).subscribe(new Observer<SupportClass> {

            /* Other methods omitted */
            public void onComplete() {
                 outerMethod();
            })
    }

    public void outerMethod() {
        blah;
    }
}

我的测试代码:

public class TestClass {

    ClassUnderTest underTest;
    Dependency dependency;

    @Before
    public void setUp() throws Exception {

        dependency = Mockito.mock(Dependency.class);
        underTest = Mockito.spy(new ClassUnderTest(dependency));

    }

    @Test
    public void method() throws 
        Mockito.when(dependency.returnObservable()).thenReturn(Observable.just(new SupportClass());

        Mockito.doNothing().when(underTest).outerMethod();

        underTest.method();
        Mockito.verify(underTest).outerMethod();

    }

}

由于某种原因我似乎无法弄明白,即使我已经通过调试器中的逐行逐步手动验证,Mockito也无法检测到正在调用outerMethod()。我还验证了对依赖项对象的调用返回了具有正确内容的正确observable,并且调用了onComplete()和outerMethod()方法。我很困惑为什么Mockito没有检测到它。

这是它吐出的错误:

Wanted but not invoked:
classUnderTest.outerMethod();
-> at (file and line number)

However, there was exactly 1 interaction with this mock:
classUnderTest.method();
-> at (file and line number)

我有什么明显的遗失吗?

1 个答案:

答案 0 :(得分:2)

您在计划程序之间进行了更改,因此在测试时可能会导致一些问题(您的代码可能会在调用实际方法之前到达verify方法

检查this article,解释如何使用RxJava和Mockito

测试异步代码

<强> TL; DR

添加TestRule,将所有调度程序设置为trampoline,使其同步运行:

public class TrampolineSchedulerRule implements TestRule {
  @Override
  public Statement apply(final Statement base, Description d) {
    return new Statement() {
      @Override
      public void evaluate() throws Throwable {
        RxJavaPlugins.setIoSchedulerHandler(
            scheduler -> Schedulers.trampoline());
        RxJavaPlugins.setComputationSchedulerHandler(
            scheduler -> Schedulers.trampoline());
        RxJavaPlugins.setNewThreadSchedulerHandler(
            scheduler -> Schedulers.trampoline());
        RxAndroidPlugins.setInitMainThreadSchedulerHandler(
            scheduler -> Schedulers.trampoline());

        try {
          base.evaluate();
        } finally {
          RxJavaPlugins.reset();
          RxAndroidPlugins.reset();
        }
      }
    };
  }
}