TasksRepository implements TasksDataSource { @Override public void getTasks(@NonNull final LoadTasksCallback callback) { checkNotNull(callback); if (mCachedTasks != null && !mCacheIsDirty) { callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values())); return; } if (mCacheIsDirty) { getTasksFromRemoteDataSource(callback); } else { mTasksLocalDataSource.getTasks(new LoadTasksCallback() { @Override public void onTasksLoaded(List<Task> tasks) { refreshCache(tasks); callback.onTasksLoaded(new ArrayList<>(mCachedTasks.values())); } @Override public void onDataNotAvailable() { getTasksFromRemoteDataSource(callback); } }); } } private  TasksRepository(@NonNull TasksDataSource tasksRemoteDataSource,
                            @NonNull TasksDataSource tasksLocalDataSource); static TasksRepository getInstance(TasksDataSource tasksRemoteDataSource,
                                              TasksDataSource tasksLocalDataSource); static void destroyInstance(); @Override void getTasks(@NonNull final LoadTasksCallback callback); @Override void saveTask(@NonNull Task task); @Override void completeTask(@NonNull Task task); @Override void completeTask(@NonNull String taskId); @Override void activateTask(@NonNull Task task); @Override void activateTask(@NonNull String taskId); @Override void clearCompletedTasks(); @Override void getTask(@NonNull final String taskId, @NonNull final GetTaskCallback callback); @Override void refreshTasks(); @Override void deleteAllTasks(); @Override void deleteTask(@NonNull String taskId);  }
@Test public void getTasks_repositoryCachesAfterFirstApiCall() { twoTasksLoadCallsToRepository(mLoadTasksCallback); verify(mTasksRemoteDataSource).getTasks(any(TasksDataSource.LoadTasksCallback.class)); }
@Test public void getTasks_requestsAllTasksFromLocalDataSource() { mTasksRepository.getTasks(mLoadTasksCallback); verify(mTasksLocalDataSource).getTasks(any(TasksDataSource.LoadTasksCallback.class)); }
@Test public void getTasksWithLocalDataSourceUnavailable_tasksAreRetrievedFromRemote() { mTasksRepository.getTasks(mLoadTasksCallback); setTasksNotAvailable(mTasksLocalDataSource); setTasksAvailable(mTasksRemoteDataSource, TASKS); verify(mLoadTasksCallback).onTasksLoaded(TASKS); }
@Test public void getTasksWithBothDataSourcesUnavailable_firesOnDataUnavailable() { mTasksRepository.getTasks(mLoadTasksCallback); setTasksNotAvailable(mTasksLocalDataSource); setTasksNotAvailable(mTasksRemoteDataSource); verify(mLoadTasksCallback).onDataNotAvailable(); }