Reputation: 795
I am trying to create some tests for a view model.
The view model includes a Database instantiation which calls a Database
CallRoomDatabase db = CallRoomDatabase.getDatabase(application);
where getDatabase takes an instance of the Dao()
@Database(entities = {CallEntity.class}, version = 1)
public abstract class CallRoomDatabase extends RoomDatabase {
public abstract CDao cDao();
// marking the instance as volatile to ensure atomic access to the variable
private static volatile CRoomDatabase INSTANCE;
public static CRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (CallRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
CRoomDatabase.class, "database")
// Wipes and rebuilds instead of migrating if no Migration object.
// Migration is not part of this codelab.
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
However, when trying to instantiate the model within a test, I get an error on .build()
above
java.lang.NullPointerException
at androidx.room.Room.getGeneratedImplementation(Room.java:79)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:952)
at com.s.o.dbutils.CRoomDatabase.getDatabase(CRoomDatabase.java:32)
at com.s.o.viewmodels.CViewModelTest.checkForNuTest(CViewModelTest.kt:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
At RoomDatabase.java
T db = Room.getGeneratedImplementation(mDatabaseClass, DB_IMPL_SUFFIX);
At Room.java
klass
is null
static <T, C> T getGeneratedImplementation(Class<C> klass, String suffix) {
I have tried not using the model at all at the test, just instantiate the db with
val db = CRoomDatabase.getDatabase(ApplicationProvider.getApplicationContext())
Still breaks at the same .build()
Any ideas how to get past that exception ?
We dont actually need to test the db someway, just some functions included in that model, so some way to just avoid the error would suffice.
Upvotes: 4
Views: 1900
Reputation: 2113
Room should be tested as an Android Instrumentation Test, not a JUnit test.
Update:
Use mockito to mock the database and any repositories.
Utilise mockito methods like:
Using Mockito, example. I don't know how your code works, i made some assumptions like the existence of a Call.class and what mocks you would require:
@Mock private CallRoomDatabase database;
@Mock private CRoomDatabase cRoomDatabase;
@Mock private CDao cDao;
private MyClass myClass;
@Before
public void setUp() {
// initiate all globally defined mocks annotated with @Mock
initMocks(this);
// Setup our expected behaviour from the mock
when(database.getDatabase()).thenReturn(cRoomDatabase);
myClass = new myClass(database, cDao);
}
@Test
public void givenSomeTest_whenCallingGetCall_thenInsertNewCall() {
// Setup our expected behaviour from the mock
when(cDao.getCall()).thenReturn(mock(Call.class));
// do test
// assert mock interaction with arguments and number of expected calls
verify(cDao, times(1)).insertCall(any(mock(Call.class)))
}
Upvotes: 4
Reputation: 795
To test the program in isolation from the database, I recommend implementing 2 repositories: 1 repository for the project, 1 for testing and a common interface for them. You can implement this using Dagger 2.
Upvotes: 0