I'm currently refactoring legacy code to use Android Architecture Components and set up a room db and volley requests within a kind of repository pattern. So the presentation/domain layer asks the repository to get LiveData-Objects to observe or tell him to synchronize with the server, after which old db entries are deleted and all current ones refetched from the server.
I've written tests for the synchronization part, so I'm sure, that the objects get fetched and inserted to the database correctly. But when writing a test to observe the entries of that db table (and test if the objects were saved correctly with everything there needs to be done before putting them into db) the LiveData> I'm observing, doesn't get triggered.
In the following snippet you can assume, that the synchronizeFormsWithServer(...) method does work correctly and is performing database operations asynchronously. It contains operations which deletes all Form-Objects from the db which are not present in the list of Forms fetched from the server and inserts all new ones. Since at the start of the test the database is empty this shouldn't matter that much
The test in which the observer doesn't get triggered:
@Test
public void shouldSaveFormsFromServerIntoDb() throws Exception
{
Lifecycle lifecycle = Mockito.mock(Lifecycle.class);
when(lifecycle.getCurrentState()).thenReturn(Lifecycle.State.RESUMED);
LifecycleOwner owner = Mockito.mock(LifecycleOwner.class);
when(owner.getLifecycle()).thenReturn(lifecycle);
final CountDownLatch l = new CountDownLatch(19);
formRepository.allForms().observe(owner, formList ->
{
if (formList != null && formList.isEmpty())
{
for (Form form : formList)
{
testForm(form);
l.countDown();
}
}
});
formRepository.synchronizeFormsWithServer(owner);
l.await(2, TimeUnit.MINUTES);
assertEquals(0, l.getCount());
}
The FormRepository code:
@Override
public LiveData<List<Form>> allForms()
{
return formDatastore.getAllForms();
}
The datastore:
@Override
public LiveData<List<Form>> getAllForms()
{
return database.formDao().getAllForms();
}
The formDao code (database is implemented how you'd expect it from room):
@Query("SELECT * FROM form")
LiveData<List<Form>> getAllForms();
It may very well be, that I didn't understand something about the LiveData-Components, because this is my first time using them, so maybe I got something fundamentally wrong.
Every bit of help is very much appreciated :)
PS: I stumbled across THIS post, which discusses a similar issue, but since I'm currently not using DI at all and just use a single instance of the formrepository (which has only one instance of formDao associated) I don't think it's the same problem.
Ok, so I found the solution, although I don't know, why it behaves that way.
Remember when I said "don't worry about the synchronize method"? Well... turns out there were a couple of things wrong with it, which delayed the solution further.
I think the most important error there was the method to update the objects in the database when the network response came in. I used to call
in the dao, which for unknown reasons doesn't trigger the LiveData-Observer. So I changed it to
After doing this I could get the Form-LiveData from my repository as easy as
Then subscribe to it as usual. The previously failed test looks like this now:
I know that exactly 19 Forms will get fetched from the server and then every Form will get changed once (first time I load a list containing all Forms with reduced data, and the second time I load every item from the server again replacing the old value in the db with the new value with more data).
I don't know if this will help you @joao86 but maybe you have a similar issue. If so, please make sure to comment here :)