com.evasion.framework.test.AbstractEqualsTester Maven / Gradle / Ivy
/*
* Document confidentiel - Diffusion interdite
*/
package com.evasion.framework.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.junit.Assert;
/**
* Classe d'utilitaire de test pour les Euqlas et Hashcode.
*
*/
public abstract class AbstractEqualsTester {
/**
* Verifies that equals() and hashCode() methods conforms to
* java.lang.Object contract.
*
* @param a
* L'objet de base
* @param b
* Un objet tel que a.equals(b) == true
* @param c
* Un objet tel que a.equals(c) == false
* @param d
* Un objet d�rivant de a.
*/
public void testEqualsAndHashCode(final Object a, final Object b,
final Object c, final Object d) {
Assert.assertNotNull("A must not be null.", a);
Assert.assertNotNull("B must not be null.", b);
Assert.assertEquals("B must be of same class as A", a.getClass(), b.getClass());
if (c == null) {
this.assertNotMutable(a.getClass());
} else {
Assert.assertEquals("C must be of same class as A", a.getClass(), c.getClass());
}
if (isFinalClass(a.getClass())) {
Assert.assertNull(d);
} else {
Assert.assertFalse("D must be of a different class than A", a.getClass().equals(d.getClass()));
}
this.assertNotEqualsNull(a);
this.assertIsReflexive(a);
this.assertIsSymmetric(a, b);
if (c != null) {
this.assertNotEquals(a, c);
}
if (d != null) {
this.assertEqualsSubClass(a, d);
}
}
/**
* Verifie EqualsSubClass().
*
* @param a
* objet A
* @param d
* objet D
*/
protected abstract void assertEqualsSubClass(final Object a, final Object d);
/**
* Verifie that a.equals(c) == true and that c.equals(a) == true.
*
* @param a
* objet A
* @param c
* objet C
*/
private void assertNotEquals(final Object a, final Object c) {
Assert.assertFalse("a.equals(c) returned true", a.equals(c));
Assert.assertFalse("c.equals(a) returned true", c.equals(a));
}
/**
* Assert that a.equals(null) == false.
*
* @param a
* objet A
*/
@edu.umd.cs.findbugs.annotations.SuppressWarnings("NP_LOAD_OF_KNOWN_NULL_VALUE")
private void assertNotEqualsNull(final Object a) {
// Creation d'un objet pour tester que a.equals(null) renvoi faux
// Si on ecrit a.equals(null) directement il s'agit d'une violation
Object nullObject = null;
Assert.assertFalse("a.equals(null) returned true", a.equals(nullObject));
}
/**
* Verifies that a.equals(a).
*
* @param a
* objet A
*/
private void assertIsReflexive(final Object a) {
Assert.assertTrue(a.equals(a));
Assert.assertEquals(a.hashCode(), a.hashCode());
}
/**
* Verifies that the equals method is symmetric.
*
* Assert that a.equals(b) and b.equals(a) and that a.hashCode() ==
* b.hashCode().
*
* @param a
* objet A
* @param b
* objet B
*/
private void assertIsSymmetric(final Object a, final Object b) {
Assert.assertTrue(a.equals(b));
Assert.assertTrue(b.equals(a));
Assert.assertEquals(a.hashCode(), b.hashCode());
}
/**
* Tests if the given class is final.
*
* @param clazz
* the class to test.
* @return true if the class is final, false otherwise.
*/
@SuppressWarnings("unchecked")
private boolean isFinalClass(final Class clazz) {
return Modifier.isFinal(clazz.getModifiers());
}
/**
* Verify that the given class is not mutable.
*
* @param clazz
* la class de l'objet � tester
*/
@SuppressWarnings("unchecked")
private void assertNotMutable(final Class clazz) {
final Constructor[] constructors = clazz.getConstructors();
for (int i = 0; i < constructors.length; i++) {
if (constructors[i].getParameterTypes().length != 0) {
if (!(constructors[i].getParameterTypes().length == 1 && (clazz.isAnonymousClass() || clazz.isMemberClass()))) {
Assert.fail("Class is mutable, it has non-default public constructor "
+ constructors[i]);
}
}
}
final Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName().startsWith("set")) {
Assert.fail("Class has setter method " + methods[i].getName());
}
}
}
}