Mockito runnable:想要但不调用


我想

在提交错误报告之前确保我没有做一些非常错误的事情。 这真的很奇怪。 设置:

Robolectric 3.0; mockito 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)

我再说一遍:我在验证((检查的方法中遇到了断点,但测试失败了。 我还尝试在 checkForStopped() 内部创建一个虚拟方法并对其进行验证无济于事。 我还尝试了 1000ms thread.sleep 在 robolectric UI 线程调用的两侧。 我的猜测是机器人和莫比托的反射东西之间的相互作用发生了什么?

你已经发现了一个非常有趣的预期但不直观的行为,基于这个Mockito原则:为了创建一个间谍,Mockito制作了原始对象的浅拷贝。

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

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

相关内容

  • 没有找到相关文章

最新更新