Техника для автоматической проверки согласованности equals, hashCode и CompareTo? - PullRequest
19 голосов
/ 09 марта 2012

Мне хорошо известны договорные потребности, чтобы убедиться, что hashCode соответствует equals и equals соответствует compareTo. Однако это часто нарушается на практике . Существуют ли какие-либо инструменты, методики или библиотеки, которые могут автоматически проверять эту согласованность?

Я подозреваю, что, к сожалению, ответ «нет», но было бы полезно иметь возможность провести модульный тест для такого рода вещей, который мог бы использовать библиотечный вызов или инфраструктуру, а не писать собственный тест вручную для каждого случая, где это важно.

В случае, если неясно, что я подразумеваю под последовательностью, для hashCode и equals я имею в виду следующее:

Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат.

Для equals и compareTo Я имею в виду следующее:

Естественный порядок для класса C называется равным в том и только том случае, если e1.compareTo (e2) == 0 имеет то же логическое значение, что и e1.equals (e2) для всех e1 и e2 класса С.

Ответы [ 5 ]

12 голосов
/ 09 марта 2012

В тестах Guava есть утилита под названием EqualsTester, которую мы используем в качестве повседневной части наших модульных тестов для тестирования equals и hashCode.Его использование выглядит как

new EqualsTester()
  .addEqualityGroup("hello", "h" + "ello")
  .addEqualityGroup("world", "wor" + "ld")
  .addEqualityGroup(2, 1 + 1)
  .testEquals();

, который проверяет, что все значения в одной и той же группе равны и имеют одинаковые хеш-коды, что разные группы не равны, и что различные другие инвариантывсе устраивает.Вы можете использовать его самостоятельно или просто позаимствовать его идеи.

Я был бы крайне удивлен, если бы можно было проводить тестирование без генерации или явного указания тестовых значений, просто потому, что это кажется очень вероятнымэквивалентно проблеме остановки.

5 голосов
/ 12 февраля 2013

Если вы используете JUnit, пакет расширений имеет EqualsHashCodeTestCase , который полностью проверяет как equals, так и hashCode для всего, что указано в спецификации Java (рефлексивного, транзитивного, симметричного и т. Д.). Все, что вам нужно сделать, это предоставить равный и не равный объект родительскому классу для проверки.

Поскольку метод CompareTo является частью интерфейса Comparable, он фактически разделен на другой контрольный пример - ComparabilityTestCase . Для этого требуются три объекта - один из них имеет меньшее значение, равное значение и большее значение. Переопределите их, и родительский класс позаботится об остальном.

1 голос
/ 09 ноября 2012

Я недавно использовал meanbean (http://meanbean.sourceforge.net/) для автоматического тестирования класса для контрактов equals () и hashCode () (плюс пары сеттер / получатель).

"Средний боб:

1. Проверяет, что пары методов получения и установки метода JavaBean / POJO работают правильно. 2. Проверяет, что методы equals и hashCode класса соответствуют контрактам Equals и HashCode соответственно. 3. Проверяет значение свойства в равенстве объектов. "

У меня все еще есть много вопросов, специфичных для meanbean: проверяет ли он согласованность equals () и hashCode (). К тому же я не очень старался победить его. Я считаю, что он не поддерживает CompareTo (). И я не пробовал альтернативы. Интересует чужой опыт.

1 голос
/ 09 марта 2012

Существует очень крутой инструмент под названием Корат , который может выполнять исчерпывающий поиск для проверки правильности классов Java для небольших случаев. На самом деле он смотрит на код, который выполняется для построения всех различных тестовых случаев заданного размера, которые программа может различить. Я не знаю, насколько это полезно в больших случаях, но для многих программ его можно использовать для автоматической проверки правильности работы таких случаев.

Надеюсь, это поможет!

1 голос
/ 09 марта 2012

Я написал несколько служебных методов, чтобы помочь юнит-тестированию hashCode и методам equals:

http://softsmithy.sourceforge.net/devlib/docs/api/org/softsmithy/devlib/junit/Tests.html

Библиотека с открытым исходным кодом, которую можно скачать здесь: http://sourceforge.net/projects/softsmithy/files/softsmithy-devlib/v0.1/

или с Maven:

    <dependency>
        <groupId>org.softsmithy.devlib</groupId>
        <artifactId>devlib-core</artifactId>
        <version>0.1</version>
        <scope>test</scope>
    </dependency>
...