The projects data repository is used to orchestrate the flow of data between the domain module and the remote / cache modules. In this lesson, we're going to be writing tests to ensure that the functions in this class remain functional over time.
When I try to run the bookmarkProjectCompletes() test, I'm getting a null pointer exception at this string:
val testObserver = repository.bookmarkProject(DataFactory.randomString()).test()
What could be the problem?
NPE appears because of repository.bookmarkProject() returns null.
In bookmarkProject() method we use factory.getCacheDataStore and it returns store, not cache.
But in stubBookmarkProject() we stub cache.
So if we change stubBookmarkProject() in the way we stub store:
it'll work as expected.
Joe, please check is this approach right.
I believe you are correct, but I would like to hear Joe's response. I find this implementation of the ProjectsCache class to be difficult to understand. The ProjectsDataStoreFactory picks the appropriate store, either the CacheDataStore or the RemoteDataStore for us, and the CacheDataStore has it's own ProjectsCache object built into it and even implements the setProjectAsBookmarked in the DataStore. I assume we pass a Cache object because we need to check the cache to determine what data store we're going to use, so at that point we haven't picked a dataStore yet, but I'm a bit confused as to why both the ProjectsCache and the ProjectCacheDataStore both implement setProjectAsBookmarked(). His unit test confuses me even more.
sorry that this isn't made clearer - it is true that this might be an over abstraction in some cases, the ProjectsDataStore classes are Data layer classes that manage the fetch and massaging of any data at this level - because the ProjectsDataStore interface may also define functions which that data store implementation doesn't support. For example, such as the remote layer not supporting the bookmark a project) we can handle this not being supported an isolation of the data layer rather than giving the remote layer a function that it doesn't need to (or shouldn't even) support. As mentioned in the course this is completely optional to have this extra layer of abstraction - you could ditch this internal interface and have the cache / remote layer implementations implement ProjectsDataStore directly. Personally that is what I do within my own projects, but wanted to offer the example here for those that might need that level of abstraction