Модульное тестирование: предотвращение создания дублирующихся объектов

#java #unit-testing

#java #модульное тестирование

Вопрос:

Мой профессор дал нам это домашнее задание и создал проект с кучей модульных тестов. Наша цель — убедиться, что мы можем пройти эти модульные тесты. У нас есть три класса. Класс под названием Person с именем и возрастом, говорящий класса, который расширяет Person, и посетитель класса, который также расширяет Person. Я изо всех сил пытаюсь убедиться, что нет повторяющихся людей. generateRandomString() был реализован профессором и просто возвращает случайную строку.

Я уже создал класс, его конструктор, средства получения и установки. Я также переопределил метод equals() в классе Person

Это тест, который дал нам наш профессор:

     @Test
    public void testNoDuplicatePerson() {
      HashSet<Person> people = new HashSet<Person>();
      String name = generateRandomString();
      Person p = new Speaker(name);
      people.add(p);
      assertEquals(1,people.size());
      p = new Attendee(name);
      people.add(p);
      assertEquals(1,people.size());
    }
  

Как я могу пройти этот тест?

РЕДАКТИРОВАТЬ: я решил опубликовать код трех классов:

 Person
 ```java
public abstract class Person {
    private String name;
    private int age;

    public Person(String name) {
        this.name = name;
        this.age = 0;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean equals(Object o) {
        if (o == null || !(o instanceof Person))
            return false;
        Person converted = (Person) o;
        if (this.getName().equals(converted.getName()) amp;amp; this.getAge() == converted.getAge())
            return true;
        return false;
    }
}

  

Докладчик:

 public class Speaker extends Person {

    private int fee;

    public Speaker(String name) {
        super(name);
        this.fee = 0;
    }

    public Speaker(String name, int age) {
        super(name, age);
        this.fee = 0;
    }

    public Speaker(String name, int age, int fee) {
        super(name, age);
        this.fee = fee;
    }

    public int getFee() {
        return fee;
    }

    public void setFee(int fee) {
        this.fee = fee;
    }

    public String toString() {
        return "Speaker "   this.getName()   " as a fee value of "   this.getFee()   ".";
    }
}
  

Участник:

 public class Attendee extends Person {
    private boolean paid;

    public Attendee(String name) {
        super(name);
        this.paid=false;
    }

    public Attendee(String name, int age) {
        super(name, age);
        this.paid=false;
    }

    public boolean hasPaid(){
        if (this.paid==true)
            return true;
        return false;
    }
    public String toString(){
        return "Attendee " this.getName() (this.hasPaid() ? " has":" hasn't") " paid its registration.";
    }
}
  

Комментарии:

1. Что говорит javadoc из HashSet? Когда набор считает, что объект является дубликатом другого объекта? К какому выводу вы пришли? docs.oracle.com/javase/8/docs/api/java/util/HashSet.html#add-E —

2. Вы не должны изменять сам модульный тест, только свой код. Насколько я понял, я не смогу создать Person объект, если у меня уже есть Person объект с определенным именем. Строка кода Person p=new Speaker(name); не должна работать, поскольку у меня уже есть пользователь с таким именем. Мой вопрос в том, как это решить

3. Нет. Вы можете иметь столько пользователей с одинаковыми именами, сколько захотите. Это не то, что тест проверяет. Тест проверяет то, что, если вы пытаетесь добавить пользователя в хэш-набор с тем же именем, что и у другого пользователя, уже находящегося в хэш-наборе, то хэш-набор должен рассматривать их как дубликаты (поскольку размер набора остается равным 1 после добавления). Отсюда мой вопрос: когда set считает, что объект является дубликатом другого объекта?

4. Из документации Java: » public boolean add(E e) Добавляет указанный элемент в этот набор, если он еще не присутствует. Более формально, добавляет указанный элемент e к этому набору, если этот набор не содержит элемента e2, такого что (e==null ? e2==null : e.равно(e2)). Если этот набор уже содержит элемент, вызов оставляет набор неизменным и возвращает false.» Я, очевидно, должен переопределить метод equals.

5. Вы все поняли правильно.

Ответ №1:

Как упоминалось @JB Nizet, когда вы переопределяете equals метод класса, вы должны переопределить hashCode метод. Обратите внимание на имя класса в тесте JUnit: набор хэшей. Это зависит от hashCode метода. Решение:
a. Научитесь читать документы java API. Вот ссылка на JavaDocs версии 8. Прочитайте HashSet страницу.
b. Реализуйте hashCode метод. У вас явно есть доступ в Интернет, поэтому, если вы не знаете, как реализовать hashCode метод, попробуйте поискать в Google «как мне реализовать метод Java hashCode».

Подсказка: String уже реализует метод hashCode.