Reputation: 11537
My application combines 3 ContentProvider data sources into one UI. I want to be sure everything is laid out correctly, hence I am trying to provide mock content providers with predefined data (and later take screenshots of that, but that's step 2).
The project structure is:
/app
/app/homeapp
/app/sourceapp
My main activity is in /app/homeapp
and reads data from /app/sourceapp
via a ContentProvider
. It also reads some data from its own ContentProvider
.
I want to be in control of the data during the test. A sample test looks like this:
@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.
}
}
(It is based on the new AndroidJUnit4 class).
Within src/androidTest/AndroidManifest.xml
I'm actually able to create a new stubbed ContentProvider
like this:
<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>
Now my key problem is how to set that DataContentProviderStubbed
as default provider.
I can not override the authority or give it an higher priority, the system will refuse this (only one ContentProvider can exist for a given authority).
For reference, I'm trying inject it into a Fragment which uses 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);
}
});
Some thinking so far:
public static
flag to control the field. Please no, very hard to maintain.Which way could work to ensure the stubbed ContentProvider is used?
Upvotes: 1
Views: 327
Reputation: 1006614
As you noted, you need different authority strings for the providers. Therefore, you need your client-side code to seamlessly use the right authority string for your build (main
versus androidTest
).
If your authority string is derived from the application ID, then you can synthesize the right authority string to use in your code from BuildConfig.APPLICATION_ID
.
If your authority strings are not readily generated from the APPLICATION_ID
, you can try to add your own buildConfigField
or resValue
to define them in build.gradle
, so you can reference them in your Java.
If you want to minimize code duplication, you can use manifest placeholders to define the authority strings in the manifest from values in Gradle. You can then use a common source of knowledge (e.g., gradle.properties
) to populate both the manifest placeholder and the buildConfigField
/resValue
.
Now, the catch for the above paragraph is that I know it works for product flavors. I have not tried it for androidTest
, and so it's possible that you cannot set up a different buildConfigField
and such for androidTest
.
Upvotes: 1