1) Не переопределять equals / hashCode только для целей модульного тестирования
Эти методы имеют семантику, и их семантика не учитывает все поля класса, чтобы сделать возможным тестовое утверждение.
2) Положитесь на библиотеку тестирования для выполнения ваших утверждений
Assert(students.contains(expectedStudent)
или что (опубликовано в ответе Джона Боллинджера):
Assert(students.stream().anyMatch(s -> expectedStudent.matches(s)));
- отличные анти-паттерны с точки зрения юнит-тестирования.
Когда утверждение не выполняется, первое, что вам нужно, это знать причину ошибки, чтобы исправить тест.
Полагаясь на логическое значение, чтобы утверждать, что сравнение списка не позволяет этого вообще.
ПОЦЕЛУЙ (Сохраняйте это простым и глупым): используйте инструменты / функции тестирования, чтобы утверждать и не изобретать колесо, потому что они обеспечат обратную связь, необходимую, когда ваш тест не пройден.
3) Не утверждать double
с equals(expected, actual)
.
Чтобы установить двойные значения, библиотеки модульного тестирования предоставляют третий параметр в утверждении, чтобы указать разрешенную дельту, такую как:
public static void assertEquals(double expected, double actual, double delta)
в JUnit 5 (аналогично в JUnit 4).
Или предпочтение от BigDecimal
до double/float
, которое больше подходит для такого сравнения.
Но это не полностью решит ваше требование, так как вам нужно указать несколько полей вашего фактического объекта. Использование цикла для этого явно не является хорошим решением.
Библиотеки Matcher предоставляют значимый и элегантный способ решения этой проблемы.
4) Использование библиотек Matcher для выполнения утверждений о конкретных свойствах объектов фактического Списка
С AssertJ:
//GIVEN
...
//WHEN
List<Student> students = getStudents();
//THEN
Assertions.assertThat(students)
// 0.1 allowed delta for the double value
.usingComparatorForType(new DoubleComparator(0.1), Double.class)
.extracting(Student::getId, Student::getName, Student::getGpa)
.containsExactly(tuple(1234, "Peter Smith", 3.89),
tuple(...),
);
Некоторые пояснения (все это функции AssertJ):
usingComparatorForType()
позволяет установить конкретный компаратор для данного типа элементов или их полей.
DoubleComparator
- это компаратор AssertJ, позволяющий учитывать эпсилон при двойном сравнении.
extracting
определяет значения для утверждения из экземпляров, содержащихся в списке.
containsExactly()
утверждает, что извлеченные значения в точности (то есть не больше, не меньше и в точном порядке) определены в Tuple
с.