У меня есть этот тест Groovy для моего приложения Spring.
given:
def mapProperties = new JSONObject().put(
"eligibility", "true").put(
"group", "group1")
when:
trackingService.sendUnifiedOnboardingAssignmentUserUpdate()
then:
1 * trackingCollector.send(new UserUpdate(mapProperties))
Tracking Collector является внешним и определяется как Spring Bean в Спецификации, которую я расширяю.
@SpringBean
TrackingCollector trackingCollector = Mock()
trackingService
находится в моем доменном слое и автоматически подключается
Тест должен пройти успешно, но это не так.
Too few invocations for:
1 * trackingCollector.send(new UserUpdate(mapProperties)) (0 invocations)
Unmatched invocations (ordered by similarity):
1 * trackingCollector.send(UserUpdate(super=Event(properties = {"group":"group1","eligibility":"true"})))
One or more arguments(s) didn't match:
0: argument == expected
| | |
| | UserUpdate(super=Event(properties = {"group":"group1","eligibility":"true"})) (com.package.tracking.collector.UserUpdate@4fe5aac9)
| false
UserUpdate(super=Event(properties = {"group":"group1","eligibility":"true"})) (com.package.tracking.collector.UserUpdate@48bb5a69)
Отличие только в @....
. Но почему Groovy не проверяет фактическое значение объекта, а вместо этого выбирает сравнение объектов? Что мне нужно сделать, чтобы пройти тест в этом случае?
Очень хороший вопрос! @LeonardBrünings UserUpdate
расширяет Event
в отдельной библиотеке. UserUpdate
имеет @EqualsAndHashCode(callSuper = true)
из Ломбока, что в основном означает вызов суперкласса для равных. А еще у Event
есть @Data
с Ломбока, который тоже реализует equals.
В любом случае, либо equals
, либо hashCode
, либо оба не делают того, что вы ожидаете в вашем случае. Где твой MCVE? Никто не сможет отладить ваш неполный набор сниппетов.
База кода чрезвычайно велика, я пытался создать MCVE, но без включения большего количества информации я просто не понимаю, как это возможно. Я уже добавил, какие аннотации Lombok я использую для соответствующих классов. Я подозреваю, что это либо Lombok, где @Data
не дает мне equals
функцию, которую я хочу, либо Groovy + Spock, где параметр вызова требует точного совпадения под капотом, сравнивая ссылки, а не значения. Я искал ответ, который помог ответить на этот конкретный вопрос, а также, возможно, помочь мне исправить это.
Спок использует Groovy Truth, поэтому он просто сравнивает эти два объекта с equals
. Что произойдет, если вы вручную создадите два отдельных экземпляра и просто выполните на них assert a == b
?
Выполнение этого по-прежнему не соответствует утверждению. Это хорошая новость, масштаб проблемы сужается. Таким образом, это означает, что определение другого метода equals
, который просто проверяет каждую пару ключ+значение JSONObject
или UserUpdate
в библиотеке, а не использование базового equals
Lombok (что бы это ни было), вероятно, решит мою проблему. Я попробую и обновлю свой вопрос соответственно. Все еще интересно, есть ли более элегантное решение, предназначенное только для Спока. Например, как мне заставить его проверять значение параметров вызовов по ссылке?
Ну, как я уже сказал, он не делает Java ==
, а вызывает equals
, и если это правильно реализовано, он будет делать то, что вы хотите. Если вы не хотите реализовывать его должным образом, то использование Reflective equals может сработать для вашего варианта использования.
Spock использует Groovy true, поэтому он просто сравнивает эти два объекта с equals
или compareTo
, если они реализуют Comparable
.
То, что вывод содержит идентификатор объекта, является отвлекающим маневром, Спок включает его в вывод только тогда, когда два объекта имеют одинаковую отрисовку строки, чтобы было легче понять, что не так.
Если вы не можете исправить equals
реализацию, вы можете использовать ограничение аргумента кода, чтобы вручную проверить необходимые значения.
Как отмечено в комментариях, ваши проблемы связаны с тем, что метод equals не реализован должным образом для вашего варианта использования.
Действительно ли
UserUpdate
иEvent
реализуютequals
или используютObject.equals
по умолчанию?