Comment puis-je tester la fonction hashCode () dans unit testing ?
public int hashCode(){
int result = 17 + hashDouble(re);
result = 31 * result + hashDouble(im);
return result;
}
Chaque fois que je remplace les codes égaux et de hachage, j'écris des tests unitaires conformes aux recommandations de Joshua Bloch du chapitre "Effective Java", chapitre 3. Je m'assure que le code de hachage et les égaux sont réflexifs, symétriques et transitifs. Je m'assure également que "pas égal" fonctionne correctement pour tous les membres de données.
Lorsque je vérifie l'appel d'égal à égal, je m'assure également que le hashCode se comporte comme il se doit. Comme ça:
@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());
}
Lorsque vous écrivez une fonction mathématique en général (comme du code de hachage), vous testez quelques exemples dans vos tests jusqu'à ce que vous soyez convaincu que la fonction fonctionne comme prévu. Le nombre d’exemples dépend de votre fonction.
Pour une fonction de code de hachage, je pense que vous testez au moins deux objets distincts, considérés comme égaux, ayant le même code de hachage. Comme
assertNotSame(obj1, obj2); // don't cheat
assertEquals(obj1.hashcode(), obj2.hashcode());
De plus, vous devez vérifier que deux valeurs différentes ont des codes de hachage différents pour éviter de mettre en œuvre hashcode()
comme return 1;
.
Créez plusieurs (des millions) d'objets reproductibles de manière aléatoire, ajoutez tous les hashCodes à un ensemble et vérifiez que vous obtenez presque et de nombreuses valeurs unqiue comme nombre d'identifiants de génération. Pour les rendre reproductibles de manière aléatoire, utilisez une graine aléatoire fixe.
De plus, vérifiez que vous pouvez ajouter ces éléments à un hachage et les retrouver. (Utiliser un objet différent avec les mêmes valeurs)
Assurez-vous que votre equals () correspond à votre comportement hashCode (). Je voudrais également vérifier que vos champs sont tous définitifs.
hashCode est écrasé afin de rendre les instances avec les mêmes champs identiques pour HashSet/HashMap, etc. Le test Junit doit donc affirmer que deux instances différentes avec les mêmes valeurs renvoient un hashCode identique.
Je ne pense pas qu'il soit nécessaire de tester à l'unité une méthode de hashcode. Surtout s'il est généré par votre IDE ou par un HashCodeBuilder
(Apache commons)
Mis à part le test @duffymo pour le hashcode, qu'il soit réflexif, symétrique et transitif, un autre moyen de test serait via "Map", où les hashcodes sont vraiment utiles.
@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));
}