android - Mockito 可运行 : wanted but not invoked?

标签 android mockito robolectric

在提交错误报告之前,我想确保自己没有做错什么。这真的很奇怪。设置:

机器人电子 3.0;模拟 1.10.19

被测单元:

public BbScrollView( Context context ){
  this( context, null );
}

public BbScrollView( Context context, AttributeSet attrs ) {
  super( context, attrs );

  mScrollTask = new Runnable() {

    public void run() {
      checkForStopped();
    }
  };
}

public void checkForStopped(){
  int newPosition = getScrollY();
  // the rest is irrelevant , but I hit a breakpoint here.
}

public void startScrollTask() {
  mInitialPosition = getScrollY();
  postDelayed( mScrollTask, mTimeUntilNextCheckForStopped );
}

测试:

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class BbScrollViewTests {

  @Test
  public void test_startScrollTask(){
    BbScrollView uut = spy( new BbScrollView( RuntimeEnvironment.application ) );

    // This calls the method above that enqueues the runnable
    uut.startScrollTask();

    // Robolectric runs the runnable
    ShadowLooper.runUiThreadTasksIncludingDelayedTasks();

    // I can hit a breakpoint inside this method but verify() fails
    verify( uut ).checkForStopped();
  }
}

测试失败:

Wanted but not invoked:
bbScrollView.checkForStopped();
-> at com.myapp.android.BbKit.test.view.BbScrollViewTests.test_startScrollTask(BbScrollViewTests.java:62)

However, there were other interactions with this mock:
bbScrollView.startScrollTask();
-> at com.myapp.android.BbKit.test.view.BbScrollViewTests.test_startScrollTask(BbScrollViewTests.java:58)

bbScrollView.getScrollY();
-> at com.myapp.android.BbKit.test.view.BbScrollViewTests.test_startScrollTask(BbScrollViewTests.java:58)

bbScrollView.$$robo$getData();
-> at com.myapp.android.BbKit.test.view.BbScrollViewTests.test_startScrollTask(BbScrollViewTests.java:58)

bbScrollView.postDelayed(
    com.myapp.android.BbKit.view.BbScrollView$1@7f830761,
    100
);
-> at com.myapp.android.BbKit.test.view.BbScrollViewTests.test_startScrollTask(BbScrollViewTests.java:58)

bbScrollView.$$robo$getData();
-> at com.myapp.android.BbKit.test.view.BbScrollViewTests.test_startScrollTask(BbScrollViewTests.java:58)

我重复一遍:我在 verify() 检查的方法中设置了断点,但测试失败了。我还尝试在 checkForStopped() 中创建一个虚拟方法并对其进行验证但无济于事。我还在 robolectric UI 线程调用的任一侧尝试了 1000ms thread.sleep。我的猜测是 robolectric 和 mockito 的反射 Material 之间的相互作用正在发生什么?

最佳答案

根据 Mockito 原则,您发现了一些非常有趣的预期但不直观的行为:创建 spy ,Mockito makes a shallow copy of the original object .

当您在构造函数中创建匿名内部 Runnable 时,Runnable 包含对 BbScrollView.this 的隐式引用,您的原始 BbScrollView 对象。然后,您在创建 spy 时创建一个副本,并且对原始 BbScrollView 的引用仍然存在。这意味着您对 checkForStopped 的调用发生在 Mockito 无法观察到的原始对象上,而不是 spy 。

解决此问题的一种方法是将您的匿名内部 Runnable 创建移动到您的 startScrollTask​​ 方法,在 spy 上调用,因此 this 指的是 spy 。当 Runnable 运行时,它将调用 spy 而不是真实对象上的方法,允许 Mockito 拦截和验证调用。

关于android - Mockito 可运行 : wanted but not invoked?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33656249/

相关文章:

android - 测试 Activity 从服务开始

java - Robolectric Resources$NotFoundException 找不到库 (aar) 资源

android - 将 ViewGroup 添加到 ViewGroup

java - Python(服务器)从Java(客户端)接收数据在单独的行中..(TCP)

java - Mockito 模拟无法正常工作

java - 为什么 null Mock 对象不会抛出 NullPointerException?

java - Android Studio 单元测试支持与 robolectric

android - App杀死Android后恢复

android - 在SQLite数据库浏览器中创建时间戳

Mockito错误 "The system cannot find the path specified"