使用 MockContentResolver 查询导致 NullPointerException [英] Query using MockContentResolver leads to NullPointerException

查看:15
本文介绍了使用 MockContentResolver 查询导致 NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个 JUnit 测试类,它扩展了 ActivityInstrumentationTestCase2.测试(以及我们正在测试的类)使用扩展 ContentProviderCommentContentProvider 来访问 SQLite 数据库,我们得到一个 NullPointerException [下面的完整堆栈跟踪] 在提供程序上运行查询时.

We have a JUnit test class which extends ActivityInstrumentationTestCase2<CommentActivity>. The test (and the class we're testing) use CommentContentProvider, which extends ContentProvider, to access the SQLite database, and we're getting a NullPointerException [full stack trace below] when running a query on the provider.

我们实例化一个 MockContentResolver,如下所示:>

We instantiate a MockContentResolver as shown:

MockContentResolver mResolver;

public void setUp() {
    super.setUp();
    CommentContentProvider ccp = new CommentContentProvider();
    mResolver = new MockContentResolver();
    mResolver.addProvider(CommentContentProvider.AUTHORITY, ccp);
}

稍后,在我们的测试中,当调用以下代码时,我们得到一个NullPointerException:

Later on, in our tests, when calling the following code, we get a NullPointerException:

Cursor mCursor = mResolver.query(Uri.parse(mUri), null, null, null, null);

即使我们等待实例化 MockContentResolver 直到我们获得被测活动的副本,我们也会得到相同的结果:

We get the same result even if we wait to instantiate MockContentResolver until we have a copy of the activity under test:

mActivity = getActivity();
MockContentResolver mResolver = new MockContentResolver(mActivity);

我们已经验证 mActivity 不为空.

We have verified that mActivity is not null.

一位同事通过Android源码(我们系统没有安装),发现错误的近因是getContext()第一行 ContentProvider.enforceReadPermissionInner().

A colleague stepped through the Android source (not installed on our system) and found that the proximate cause of the error is that getContext() returns null on the first line of ContentProvider.enforceReadPermissionInner().

我们查看了这个问题,最初看起来很相似,但我认为这是一个完全不同的问题.这个问题也是一个类似的问题症状,但他们没有实例化他们的 MockContentResolver.我们在实例化我们的实例时遇到问题.

We took a look at this question which originally seemed similar, but I think it was a different problem entirely. This question is also a similar symptom of a problem, but they didn't instantiate their MockContentResolver. We are having problems instantiating ours.

这是我们得到的堆栈跟踪:

Here's the stack trace we're getting:

java.lang.NullPointerException
at android.content.ContentProvider$Transport.enforceReadPermissionInner(ContentProvider.java:449)
at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:394)
at android.content.ContentProvider$Transport.query(ContentProvider.java:194)
at android.content.ContentResolver.query(ContentResolver.java:461)
at android.content.ContentResolver.query(ContentResolver.java:404)
at packagename.test.FooActivityTest.getNumCommentsForRecipient(FooActivityTest.java:84)
at packagename.test.FooActivityTest.testCommentEntryInternal(FooActivityTest.java:91)
at packagename.test.FooActivityTest.testCommentEntry1(FooActivityTest.java:108)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.access$000(InstrumentationTestCase.java:36)
at android.test.InstrumentationTestCase$2.run(InstrumentationTestCase.java:189)
at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:1719)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4998)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
at dalvik.system.NativeStart.main(Native Method)

我们如何解决这个问题?

How can we resolve this problem?

推荐答案

在测试内部依赖另一个内容提供者来写掉一些元数据的内容提供者时,我遇到了类似的问题.

I had a similar problem when testing a content provider that internally relied on another content provider to write away some metadata.

首先,您最好使用 ProviderTestCase2 类,它可以为您设置被测提供程序的大部分工作.它可能会让你的生活变得更加轻松.(对我来说这还不够,因为它只能通过一个提供程序帮助您,我需要两个.)

First of all, you may be better off using the ProviderTestCase2 class, which will do most of the work for setting up the provider under test for you. It might make your life considerably easier. (For me this wasn't enough because it'll only help you with one provider, I needed two.)

如果这对您来说是不可能的,这对我有用:

If this is not possible for you, here's what did the trick for me:

您的查询失败,因为您的提供者从未附加过上下文.您必须自己手动执行此操作 - 文档忘记提及.这样做:

Your query fails because your provider never had a context attached to it. You have to do this yourself, manually - which the documentation forgets to mention. Do this:

public void setUp() {
    super.setUp();
    CommentContentProvider ccp = new CommentContentProvider();

    // Add this line to attach context:
    ccp.attachInfo(mActivity, null);

    mResolver = new MockContentResolver();
    mResolver.addProvider(CommentContentProvider.AUTHORITY, ccp);
}

我不能 100% 确定要附加哪个上下文以使您的测试与世界其他地方隔离,ProviderTestCase2 设置了整个模拟上下文链.如果您遇到问题,请查看 RenamingDelegatingContexthref="http://developer.android.com/reference/android/test/IsolatedContext.html">IsolatedContext,这些是 ContentProviderTestCase2 使用的.(看看它的 setUp() 方法).

I'm not 100% sure which context to attach to keep your test isolated from the rest of the world, ProviderTestCase2 sets up a whole chain of mock contexts. If you're having issues, look at RenamingDelegatingContext and IsolatedContext, those are the ones ContentProviderTestCase2 uses. (Have a look at its setUp() method).

希望对你有帮助!

这篇关于使用 MockContentResolver 查询导致 NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆