使用外部模拟ContentProvider的androidTest

使用外部模拟ContentProvider的androidTest,android,android-testing,Android,Android Testing,我的应用程序将3个ContentProvider数据源合并到一个UI中。 我希望确保所有内容都正确布局,因此我尝试向模拟内容提供商提供预定义数据(稍后截图,但这是第2步) 项目结构为: /app /app/homeapp /app/sourceapp 我的主要活动是在/app/homeapp中,通过内容提供者从/app/sourceapp读取数据。它还从自己的ContentProvider读取一些数据 我想在测试期间控制数据。示例测试如下所示: @RunWith(AndroidJUnit4.c

我的应用程序将3个ContentProvider数据源合并到一个UI中。 我希望确保所有内容都正确布局,因此我尝试向模拟内容提供商提供预定义数据(稍后截图,但这是第2步)

项目结构为:

/app
/app/homeapp
/app/sourceapp
我的主要活动是在
/app/homeapp
中,通过
内容提供者从
/app/sourceapp
读取数据。它还从自己的
ContentProvider
读取一些数据

我想在测试期间控制数据。示例测试如下所示:

@RunWith(AndroidJUnit4.class)
@MediumTest
public class MainAppActivityTest {
    @Rule
    public ActivityTestRule<MusicHomeActivity_> activityRule = new ActivityTestRule<>(MusicHomeActivity_.class);

    @Test
    public void testDataDisplayed() throws Exception {
        // Check view in target.
        // Ensure items are displayed properly.
        // Take screenshot, compare.
    }
}
<manifest
    package="com.company.app"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <application>

        <provider
            android:name="com.company.app.DataContentProviderStubbed"
            android:authorities="com.company.app.data.stubbed"
            android:exported="true"/>

    </application>
</manifest>
现在我的关键问题是如何将
DataContentProviderStubbed
设置为默认提供程序。 我无法覆盖权限或赋予其更高的优先级,系统将拒绝此操作(对于给定的权限,只能存在一个ContentProvider)

作为参考,我尝试将其注入到使用
LoaderManager
的片段中:

// onViewCreated
getLoaderManager().restartLoader(LOADER_DEVICES, null, new LoaderManager.LoaderCallbacks<Cursor>() {
    @Override
    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
        return new CursorLoader(context, CONTENT_URI, PROJECTION,
                DataContentDescriptor.Device.DEVICE_TYPE + " = ? AND " + DataContentDescriptor.Device.UDN + " != ?",
                new String[]{TYPE_SERVER, myUdn}, null);
    }

    @Override
    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
        deviceAdapter.setDevicesCursor(data);
    }

    @Override
    public void onLoaderReset(final Loader<Cursor> loader) {
        deviceAdapter.setDevicesCursor(null);
    }
});
//onViewCreated
getLoaderManager(){
@凌驾
公共加载器onCreateLoader(最终int-id,最终Bundle-args){
返回新的游标装入器(上下文、内容URI、投影、,
DataContentDescriptor.Device.Device_TYPE+“=”和“+DataContentDescriptor.Device.UDN+”!=?”,
新字符串[]{TYPE_SERVER,myUdn},null);
}
@凌驾
public void onLoadFinished(最终加载程序、最终光标数据){
deviceAdapter.setDevicesCursor(数据);
}
@凌驾
公共无效onLoaderReset(最终加载程序){
deviceAdapter.setDevicesCursor(空);
}
});
到目前为止,一些人认为:

  • 控制活动的实例化方式,并使用
    公共静态
    标志对其进行配置,以控制字段。请不要,很难维护
  • 在活动中,找到实现“IsRunningAndRoidTest()”的方法,并选择不同的ContentProvider权限。更好,但仍然是维护的噩梦
  • 字节码操纵,但由于com.company.app是从另一个APK运行的,因此不确定这是否存在
  • 在应用程序设计中选择内容提供者URL,并将其隐藏在ContentProviderUrlProvider(;-)类后面,但该类仍然需要根据前2点做出决定。坦率地说,我不想仅仅因为测试问题而改变软件设计

哪种方法可以确保使用存根ContentProvider?

正如您所指出的,您需要为提供者提供不同的权限字符串。因此,您需要客户端代码无缝地为构建使用正确的权限字符串(
main
androidTest

如果您的权限字符串是从应用程序ID派生的,那么您可以从
BuildConfig.application\u ID
中合成要在代码中使用的正确权限字符串

如果您的权限字符串无法从
应用程序\u ID
生成,您可以尝试添加自己的
buildConfigField
resValue
build.gradle
中定义它们,以便您可以在Java中引用它们。 如果希望最小化代码重复,可以使用清单占位符从Gradle中的值定义清单中的权限字符串。然后,您可以使用公共知识源(例如,
gradle.properties
)来填充清单占位符和
buildConfigField
/
resValue

现在,上面一段的要点是,我知道它适用于产品口味。我没有在
androidTest
中尝试过它,因此您可能无法为
androidTest
设置不同的
buildConfigField