I have started writing a simple test for my content provider. The problem is when I run the test it is using production data. How can I make sure separate test data is used from my live app data?
@RunWith(AndroidJUnit4.class)
public class MyContentProviderTest extends ProviderTestCase2<MyContentProvider>{
public MyContentProviderTest() {
super(MyContentProvider.class, MyContentProvider.AUTHORITY);
}
@Override
protected void setUp() throws Exception {
setContext(InstrumentationRegistry.getContext());
//have also tried with setContext(InstrumentationRegistry.getTargetContext());
super.setUp();
}
@Test
public void insertTest(){
ContentResolver contentResolver = getContext().getContentResolver();
assertNotNull(contentResolver);
contentResolver.insert(MyContentProvider.uri,createContentValues());
Cursor cursor = contentResolver.query(MyContentProvider.uri, Database.ALL_COLUMNS,
null, null, null);
assertNotNull(cursor);
// the test fails here because along with the row inserted above, there are also many more rows of data from using my app normally (not while under test).
assertEquals( 1, cursor.getCount());
//todo: verify cursor contents
cursor.close();
}
ContentValues createContentValues(){
ContentValues cv = new ContentValues();
cv.put(Database.COLUMN_DATETIME, LocalDateTime.now().format(Util.DATE_FORMAT));
/* ... etc */
return cv;
}
}
should I be using a different URI?
Yes. Your test code is hitting your production provider. You need your test code to hit your separate test provider, and that needs its own authority string (and, from there, Uri
).
A typical approach for new app development is to generate the authority string from the applicationId
:
<provider
android:name="MyContentProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true" />
Your authority string, in Java for Uri
construction, becomes BuildConfig.APPLICATION_ID+".provider"
. This requires that you be using Gradle for your builds (e.g., via Android Studio) or have an equivalent facility in whatever build system you are using.
Your test code will get a separate testApplicationId
automatically, or you can override it in Gradle if you want. Having a separate application ID for production vs. test means that you have separate internal storage, and having your code always refer to the correct provider (via the application ID-specific authority) means that your test code will use the test provider and the test build's internal storage, and your production code will use the production provider and the production build's internal storage.