[JAVA] Test Data Builder-Muster ~ Verbessert die Wartbarkeit des Testcodes

Dieser Artikel ist der 17. Tag von Android 2 Adventskalender 2016 - Qiita.

Heute, als eines der nützlichen Muster für die Pflege von Testcode, Ich möchte das ** Test Data Builder-Muster ** einführen.

Annahme

Während der eigentlichen Entwicklung Sie schreiben häufig Testcode für Klassen, die Modelle verwenden (z. B. Wertobjekte). In diesem Fall lautet das Wertobjekt dieses Mal "User" und die Klasse, die es verwendet, "UserRepository". Fahren wir mit der Geschichte als Beispiel fort.

User.java


//Modell-
final class User {
  private final long id;
  private final String name;
  private final int age;
  private final Gender gender;
  private final String avatarUrl;
  private final Email email;

  User(long id, String name, int age, Gender gender,
      String avatarUrl, Email email) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.gender = gender;
    this.avatarUrl = avatarUrl;
    this.email = email;
  } 
}

UserRepository.java


//Klasse mit einem Modell
class UserRepository {

  User findBy(long id) {
    return null; // TODO
  }

  List<User> findAll() {
    return null; // TODO
  }

  void store(User user) {
    // TODO
  }
}

Testmethode ohne Muster

Wenn ich versuche, diesen "Repository" -Test zu schreiben, sehe ich folgendermaßen aus:

UserRepository.java


public class UserRepositoryTest {
  private UserRepository repo;

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

  @Test public void store() {
    long id = 100;
    User expected = new User(id, "", 1, Gender.MALE, "", new Email(""));

    repo.store(expected);

    User actual = repo.findBy(id);
    assertThat(actual, is(equalTo(expected)));
  }

  @Test public void findAll() {
    repo.store(new User(1, "", 1, Gender.MALE, "", new Email("")));
    repo.store(new User(2, "", 1, Gender.MALE, "", new Email("")));

    List<User> actual = repo.findAll();

    assertThat(actual.size(), is(2));
  }
}

Problem

Ich denke, das Problem mit diesem Testcode ist der Instanziierungsteil der Klasse ** User **. Hier ist der Grund.

Beides kann eine Haftung für den Langzeitbetrieb des Testcodes sein.

Testmethode mit Mustern

Um die oben genannten Probleme zu beheben, bereiten wir eine Klasse vor, die sich auf das Erstellen von Daten für die Klasse "Benutzer" zum Testen spezialisiert hat. Dies wird als ** Test Data Builder ** -Muster bezeichnet.

Der Punkt ist, dass ** für die Mitgliedsvariablen dieser Klasse Standardwerte festgelegt sind **.

UserDataBuilder.java


class UserDataBuilder {
  private long id = 1;
  private String name = "name";
  private int age = 20;
  private Gender gender = Gender.MALE;
  private String avatarUrl = "avatarUrl";
  private Email email = new EmailDataBuilder().build();

  public User build() {
    return new User(id, name, age, gender, avatarUrl, email);
  }

  public UserDataBuilder withId(long id) {
    this.id = id;
    return this;
  }

  public UserDataBuilder withName(String name) {
    this.name = name;
    return this;
  }

  ...Kürzung...

  public UserDataBuilder withEmail(Email email) {
    this.email = email;
    return this;
  }
}

Wenn Sie diese UserDataBuilder-Klasse verwenden und den vorherigen Testcode ändern, ist dies wie folgt.

UserRepositoryTest.java


public class UserRepositoryTest {
  private UserRepository repo;

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

  @Test public void store() {
    long id = 100;
    User expected = new UserDataBuilder().withId(id).build();

    repo.store(expected);

    User actual = repo.findBy(id);
    assertThat(actual, is(equalTo(expected)));
  }

  @Test public void findAll() {
    UserDataBuilder user = new UserDataBuilder();
    repo.store(user.withId(1).build());
    repo.store(user.withId(2).build());

    List<User> actual = repo.findAll();

    assertThat(actual.size(), is(2));
  }
}

Das Ergebnis der Anwendung des Musters

Was denken Sie. Im Vergleich zu dem Testcode, der keine Muster verwendet, ist dieser Code

Ich denke, es gibt so einen Verdienst.

Zusammenfassung

Die in diesem Beispiel verwendete Klasse "Benutzer" war ein Objekt, das relativ einfach zu instanziieren war. In der tatsächlichen Entwicklung gibt es jedoch viele abhängige Klassen, und es gibt viele Fälle, in denen es schwierig ist, Testdaten vorzubereiten. Zu jener Zeit

Testcode schreiben Wie wäre es mit der Anwendung dieses ** Test Data Builder-Musters **?

Verweise

Recommended Posts

Test Data Builder-Muster ~ Verbessert die Wartbarkeit des Testcodes
Test Data Builder-Muster ~ Verbessert die Wartbarkeit des Testcodes
Builder-Muster
Builder-Muster
Entwurfsmuster ~ Builder ~
Entwurfsmuster (2): Builder
String und Stringbuffer und String Builder
Builder-Muster (effektives Java)
Einführung in effektives Java durch Üben und Lernen (Builder-Muster)
Builder-Muster
Builder-Muster
RSpec-Ergebnisse der Überprüfung des Testcodes für die Benutzervalidierung
Entwurfsmuster ~ Builder ~
Entwurfsmuster (2): Builder
Builder-Muster, das eine Reihe erforderlicher Eigenschaften erzwingt
Definieren Sie die Datenquelle im Code anstelle der Eigenschaft im Spring-Boot