Как вы сравниваете объекты одного класса с разными наборами полей?

Привет.
Есть класс User с полями name, lastname, username, password, role. В нем сгенерированы hashcode() и equals().
Я ищу алгоритм, дающий возможность в каждой проверке равенства двух User самостоятельно определять какие поля надо сравнивать, а какие игнорировать.

1 тест: взять всех пользователей со страницы админки и сравнить их с данными из бд.
На странице у нас есть инфа только по username и role.
Из базы мы получим все поля описанные в классе.

Если сделать Hashset usersFromUi equals Hashset usersFromBd, то проверка зафейлится, т.к. из бд мы получим модель полнее.

Для сравнения можно:
а) заНуллить ненужные поля в объектах из бд в цикле после их получения.
или
б) Дополнить пустые поля объектов из UI полями из БД (select по username)
или
в) сделать класс-компаратор, в котором продублировать имена полей класса User, но с типами bool.
Перед сравнением создавать объект этого класса и поля, которые хочешь сравнивать инициализировать как true, потом сделать метод, который будет принимать две коллекции и компаратор и пропускать при сравнении все false поля.
г) какая-нибудь магия

А почему бы из базы не брать только username и role ?

Вариант если используете assertj: унаследоваться от org.assertj.core.api.Assertions, определить внутри метод isEqualTo(final User anotherUser). Если не используете - я бы выбрал что-то похожее на вариант “в” - класс, который знает что сравнивать и имеет статический метод для сравнения двух объектов одного класса. Варианты “а” и “б” - точно отбросил бы так как поля могут быть и read-only, и вообще - мутировать объект без необходимости как-то не хочется.

Еще вариант - создавать класс-холдер для юзера, инициализировать его данными с юайки, и внутри сделать метод типа “verifyInBase”, который через DAO вытащит нужные данные из базы и выполнит проверку. Такой вариант, имхо, лучше, так как может потребоваться проверка не только таблицы Users, а и чего-нибудь еще.

А вообще - почему используется один и тот же класс для юзера с юайки и для юзера из базы? По сути, Вам нужно сравнить сущности разных классов - скажем, UserView и UserDto. Но в любом случае, на решение это не влияет.

д) переопределить equals и hashCode таким образом, чтобы обрабатывались только необходимые поля.

3 лайка

е)

Ваш тест не уменьшает энтропию AUT и следовательно не является тестом. Напишите нормальный тест-кейс и все вопросы уйдут.

1 лайк

Не понял если честно вашего бизнесс кейса…
У меня был такой кейс банальный

  1. Есть объект юзер в базе
  2. На уай - проверяю чтобы строки правильно отображались в тч. фото аватарки (имя файла)
  3. Редактирую профайл - снова проверяю чтобы всё было правильно

Ну и 2-й кейс регистрация юзера

В любом случае это были сравнения полей на иквалс…

На вашем месте я бы не стал определять метод equals для объекта POJO, так это нарушит инкапсуляцию. Если в тесте вы получаете только username and role, сделайте отдельный метод для проверки данных в тесте. Так вы не загоните себя в рамки ограничения теста при дальнейшей разработке. Не ищите сложных решений, очень часто самое простое и есть верное :).