【问题标题】:androidTest with external mocked ContentProvider带有外部模拟 ContentProvider 的 androidTest
【发布时间】:2016-03-03 20:03:10
【问题描述】:

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

项目结构为:

/app
/app/homeapp
/app/sourceapp

我的主要活动在/app/homeapp,并通过ContentProvider/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.
    }
}

(它基于新的 AndroidJUnit4 类)。

src/androidTest/AndroidManifest.xml 内,我实际上可以像这样创建一个新的存根ContentProvider

<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);
    }
});

目前的一些想法:

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

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

【问题讨论】:

    标签: android android-testing


    【解决方案1】:

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

    如果您的权限字符串源自应用程序 ID,那么您可以从 BuildConfig.APPLICATION_ID 合成正确的权限字符串以在您的代码中使用。

    如果您的权限字符串不容易从APPLICATION_ID 生成,您可以尝试添加自己的buildConfigFieldresValue 以在build.gradle 中定义它们,这样您就可以在Java 中引用它们。 如果您想最大限度地减少代码重复,您可以使用清单占位符从 Gradle 中的值定义清单中的权限字符串。然后,您可以使用通用知识源(例如 gradle.properties)来填充清单占位符和 buildConfigField/resValue

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

    【讨论】:

      猜你喜欢
      • 2016-06-01
      • 1970-01-01
      • 2018-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多