我正在使用ApplicationTestCase测试一个Android应用程序。我想模拟我的AsyncTasks之一(示例简化为显示问题):
public class Foo extends AsyncTask<Void,Void,Void> { @Override protected Void doInBackground(Void... unused) { return null; } }
因此,为了设置测试,我做了以下工作:
private Foo mockFoo; @Override protected void setUp() throws Exception { super.setUp() mockFoo = mock(Foo.class); createApplication(); }
然后,实际测试如下:
public void testAsyncTaskMock() { mockFoo.execute(); verify(mockFoo).execute(); }
但是mockFoo.execute();运行时出现异常:
mockFoo.execute();
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.AsyncTask$Status.ordinal()' on a null object reference
为什么模拟AsyncTask的技术不起作用?
请注意,createApplication();在这种简单情况下,删除会导致问题消失,但是对于我的实际测试,我确实需要创建应用程序。
createApplication();
AsyncTask.execute是final,Mockito无法模拟final类或方法。
无法模拟最终方法-执行它们的实际行为没有任何异常。Mockito无法警告您嘲笑最终方法,因此请保持警惕。
具体来说,这是因为Java可以在编译时解析链接,这意味着Mockito不能使用其生成的子类和方法重写来更改行为。
您可以选择使用Powermock(使用特殊的类加载器重写旧行为)或Robolectric,其功能相同,但是将类替换为Android特定的测试友好的替代实现(“影子”),包括AsyncTask的替代实现。