The following is the first few sections of a chapter from Exploring Android, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Extending the Repository

Right now, our repository makes to-do items available… and that’s it. We need to be able to create, update, and delete to-do items as well. That’s the focus on this tutorial: extending the repository for the full set of CRUD operations (Create, Read, Update, and Delete). And, along the way, we will extend our tests of the repository to match.

This is a continuation of the work we did in the previous tutorial. The book’s GitHub repository contains the results of the previous tutorial as well as the results of completing the work in this tutorial.

Step #1: Adding and Testing add()

Add this add() method to ToDoRepository:

  public void add(ToDoModel model) {
    items.add(model);
  }

Right now, we do not need to do anything more elaborate than just appending the new model to the list.

However, in terms of testing this (and the upcoming edit() and delete() methods), we have a problem. Right now, RepoTests uses the singleton instance of ToDoRepository:

package com.commonsware.todo;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

@RunWith(AndroidJUnit4.class)
public class RepoTests {
  private ToDoRepository repo;

  @Before
  public void setUp() {
    repo=ToDoRepository.get();
  }

  @Test
  public void getAll() throws Exception {
    assertEquals(3, repo.all().size());
  }
}

That is fine for read-only operations, but once we start adding, editing, and deleting models, we are changing what is in the repository, and that may affect future tests using that repository. Ideally, we would use a fresh repository for each test method.

To make this work, remove the private keyword from the ToDoRepository constructor, so it is package-private:

  ToDoRepository() {
    items.add(ToDoModel.creator()
      .description("Buy a copy of _Exploring Android_")
      .notes("See https://wares.commonsware.com")
      .isCompleted(true)
      .build());
    items.add(ToDoModel.creator()
      .description("Complete all of the tutorials")
      .build());
    items.add(ToDoModel.creator()
      .description("Write an app for somebody in my community")
      .notes("Talk to some people at non-profit organizations to see what they need!")
      .build());
  }

Our instrumentation tests happen to be in the same Java package as the production code. This means that we are doing white-box testing: we can access package-private members, such as constructors.

Modify setUp() in RepoTests to create a new ToDoRepository:

  @Before
  public void setUp() {
    repo=new ToDoRepository();
  }

Then, add an add() test method to RepoTests:

  @Test
  public void add() {
    ToDoModel model=ToDoModel.creator()
      .isCompleted(true)
      .description("foo")
      .build();

    repo.add(model);

    List<ToDoModel> models=repo.all();

    assertEquals(4, models.size());
    assertThat(models, hasItem(model));
  }

Here, we:

The hasItem() method will show up in red, as that is a static method that we can import. If you use Alt-Enter (Option-Return on macOS) for the import quick-fix, you will get a few candidate implementations, all from the hamcrest test library. Choose the org.hamcrest.Matchers.hasItem edition of the method to import.

If you run RepoTests again from the Android Studio toolbar — or by clicking on the double-play icon in the gutter next to the class declaration — you should see that this test succeeds.

Step #2: Adding and Testing replace()

The preview of this section was accidentally identified as an Android 'tasty treat' by the Cookie Monster.

Step #3: Adding and Testing delete()

The preview of this section was stepped on by Godzilla.

What We Changed

The preview of this section was the victim of a MITM ('Martian in the middle') attack.