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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mockito:验证来自内部匿名类的方法调用相关的知识,希望对你有一定的参考价值。

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

有什么明显我想念的吗?

答案

您正在调度程序之间进行更改,因此在测试时可能会导致一些问题(在调用实际方法之前,您的代码可能会达到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();
        }
      }
    };
  }
}

以上是关于Mockito:验证来自内部匿名类的方法调用的主要内容,如果未能解决你的问题,请参考以下文章

java 匿名对象,内部类,修饰符,代码块

java内部类的匿名内部类

来自 void 类的模拟异步调用

代码片--练习匿名内部类

Lambda 表达式

阶段1 语言基础+高级_1-3-Java语言高级_02-继承与多态_第7节 内部类_14_匿名内部类的注意事项