Как проверить функцию hashCode() в модульное тестирование?
public int hashCode(){
int result = 17 + hashDouble(re);
result = 31 * result + hashDouble(im);
return result;
}
Как проверить функцию hashCode() в модульное тестирование?
public int hashCode(){
int result = 17 + hashDouble(re);
result = 31 * result + hashDouble(im);
return result;
}
Всякий раз, когда я переопределяю equals и хэш-код, я пишу модульные тесты, которые следуют рекомендациям Джошуа Блоха в "Эффективной Java". Глава 3. Я убеждаюсь, что equals и хэш-код являются рефлексивными, симметричными и транзитивными. Я также убеждаюсь, что "не равно" работает правильно для всех членов данных.
Когда я проверяю вызов на равные, я также убеждаюсь, что hashCode ведет себя так, как должен. Вот так:
@Test
public void testEquals_Symmetric() {
Person x = new Person("Foo Bar"); // equals and hashCode check name field value
Person y = new Person("Foo Bar");
Assert.assertTrue(x.equals(y) && y.equals(x));
Assert.assertTrue(x.hashCode() == y.hashCode());
}
Когда вы пишете математическую функцию вообще (например, хеш-код), вы тестируете несколько примеров в своих тестах, пока не убедитесь, что функция работает так, как ожидалось. Сколько примеров зависит от вашей функции.
Для функции хеш-кода я бы подумал, что вы тестируете по крайней мере два разных объекта, которые считаются равными, имеют одинаковый хеш-код. Как
assertNotSame(obj1, obj2); // don't cheat
assertEquals(obj1.hashcode(), obj2.hashcode());
Далее вы должны проверить, что два разных значения имеют разные хэш-коды, чтобы избежать реализации hashcode()
как return 1;
.
Создайте много (миллионы) воспроизводимо случайных объектов и добавьте все хэш-коды в Set и убедитесь, что вы получаете почти и многие значения unqiue в качестве числа генерирующих идентификаторов. Чтобы сделать их воспроизводимым случайным образом использовать фиксированное случайное семя.
Кроме того, вы можете добавить эти элементы в HashSet и найти их снова. (Использование объекта differnt с одинаковыми значениями)
Убедитесь, что ваш equals() соответствует вашему поведению hashCode(). Я также хотел бы проверить, что ваши поля окончательны.
hashCode переопределяется, чтобы сделать экземпляры с одинаковыми полями одинаковыми для HashSet/HashMap и т.д. Поэтому тест Junit должен утверждать, что два разных экземпляра с одинаковыми значениями возвращают идентичный хэш-код.
Я не думаю, что есть необходимость в модульном тестировании метода хэш-кода. Особенно, если она генерируется либо вашей IDE, либо HashCodeBuilder
(apache commons)
Помимо теста @duffymo для хеш-кода, являющегося рефлексивным, симметричным и транзитивным, другим способом тестирования будет через "Карта", где хэш-коды действительно пригодится.
@Test
public void testHashcode() {
Person p1 = new Person("Foo Bar");
Person p2 = new Person("Foo Bar");
Map<Person, String> map = new HashMap<>();
map.put(p1, "dummy");
Assert.assertEquals("dummy", map.get(p2));
}