为什么不使用AsyncTask进行模拟?

Lev*_*evi 1 java android mockito android-asynctask

我正在使用ApplicationTestCase测试Android应用.我想模拟我的一个AsyncTasks(示例简化以显示问题):

public class Foo extends AsyncTask<Void,Void,Void> {
  @Override
  protected Void doInBackground(Void... unused) {
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)

所以为了设置我的测试,我做了以下事情:

private Foo mockFoo;

@Override
protected void setUp() throws Exception {
  super.setUp()

  mockFoo = mock(Foo.class);

  createApplication();
}
Run Code Online (Sandbox Code Playgroud)

然后实际测试如下:

public void testAsyncTaskMock() {
  mockFoo.execute();
  verify(mockFoo).execute();
}
Run Code Online (Sandbox Code Playgroud)

但是我在mockFoo.execute();运行时遇到异常:

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.AsyncTask$Status.ordinal()' on a null object reference
Run Code Online (Sandbox Code Playgroud)

为什么模拟AsyncTask的技术不起作用?

请注意,createApplication();在这种简单的情况下,删除会导致问题消失,但对于我的实际测试,我确实需要创建应用程序.

Jef*_*ica 6

AsyncTask.execute是最终的,Mockito不能模拟最终的类或方法.

  • 无法模拟最终方法 - 它们的实际行为在没有任何异常的情况下执行.Mockito无法警告你嘲笑最终方法,所以请保持警惕.

具体来说,这是因为Java可以在编译时解析链接,这意味着Mockito无法使用其生成的子类和方法覆盖来更改行为.

你可以选择使用Powermock,它使用一个特殊的类加载器来重写旧的行为,或者Robolectric,它使用特定于Android的测试友好的替代实现("阴影")替换类,包括AsyncTask.