Mockito:验证来自内部匿名类的方法调用

问题描述 投票:1回答:1

我有一个测试类,其中包含一个具有内部匿名类的方法。匿名类中的一个方法从被测试的类中调用一个方法,但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)

有什么明显我想念的吗?

java mockito anonymous-class verify method-call
1个回答
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();
        }
      }
    };
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.