下列类用作equals/hashCode契约(Contract)的通用测试器。它是自家测试框架的一部分。

  • 您如何看待?
  • 我如何(强烈)测试该类(class)?
  • Junit理论的很好用吗?

  • 类(class):
    @Ignore
    @RunWith(Theories.class)
    public abstract class ObjectTest {
    
        // For any non-null reference value x, x.equals(x) should return true
        @Theory
        public void equalsIsReflexive(Object x) {
            assumeThat(x, is(not(equalTo(null))));
            assertThat(x.equals(x), is(true));
        }
    
        // For any non-null reference values x and y, x.equals(y)
        // should return true if and only if y.equals(x) returns true.
        @Theory
        public void equalsIsSymmetric(Object x, Object y) {
            assumeThat(x, is(not(equalTo(null))));
            assumeThat(y, is(not(equalTo(null))));
            assumeThat(y.equals(x), is(true));
            assertThat(x.equals(y), is(true));
        }
    
        // For any non-null reference values x, y, and z, if x.equals(y)
        // returns true and y.equals(z) returns true, then x.equals(z)
        // should return true.
        @Theory
        public void equalsIsTransitive(Object x, Object y, Object z) {
            assumeThat(x, is(not(equalTo(null))));
            assumeThat(y, is(not(equalTo(null))));
            assumeThat(z, is(not(equalTo(null))));
            assumeThat(x.equals(y) && y.equals(z), is(true));
            assertThat(z.equals(x), is(true));
        }
    
        // For any non-null reference values x and y, multiple invocations
        // of x.equals(y) consistently return true  or consistently return
        // false, provided no information used in equals comparisons on
        // the objects is modified.
        @Theory
        public void equalsIsConsistent(Object x, Object y) {
            assumeThat(x, is(not(equalTo(null))));
            boolean alwaysTheSame = x.equals(y);
    
            for (int i = 0; i < 30; i++) {
                assertThat(x.equals(y), is(alwaysTheSame));
            }
        }
    
        // For any non-null reference value x, x.equals(null) should
        // return false.
        @Theory
        public void equalsReturnFalseOnNull(Object x) {
            assumeThat(x, is(not(equalTo(null))));
            assertThat(x.equals(null), is(false));
        }
    
        // Whenever it is invoked on the same object more than once
        // the hashCode() method must consistently return the same
        // integer.
        @Theory
        public void hashCodeIsSelfConsistent(Object x) {
            assumeThat(x, is(not(equalTo(null))));
            int alwaysTheSame = x.hashCode();
    
            for (int i = 0; i < 30; i++) {
                assertThat(x.hashCode(), is(alwaysTheSame));
            }
        }
    
        // If two objects are equal according to the equals(Object) method,
        // then calling the hashCode method on each of the two objects
        // must produce the same integer result.
        @Theory
        public void hashCodeIsConsistentWithEquals(Object x, Object y) {
            assumeThat(x, is(not(equalTo(null))));
            assumeThat(x.equals(y), is(true));
            assertThat(x.hashCode(), is(equalTo(y.hashCode())));
        }
    
        // Test that x.equals(y) where x and y are the same datapoint
        // instance works. User must provide datapoints that are not equal.
        @Theory
        public void equalsWorks(Object x, Object y) {
            assumeThat(x, is(not(equalTo(null))));
            assumeThat(x == y, is(true));
            assertThat(x.equals(y), is(true));
        }
    
        // Test that x.equals(y) where x and y are the same datapoint instance
        // works. User must provide datapoints that are not equal.
        @Theory
        public void notEqualsWorks(Object x, Object y) {
            assumeThat(x, is(not(equalTo(null))));
            assumeThat(x != y, is(true));
            assertThat(x.equals(y), is(false));
        }
    }
    

    用法:
    import org.junit.experimental.theories.DataPoint;
    
    public class ObjectTestTest extends ObjectTest {
    
        @DataPoint
        public static String a = "a";
        @DataPoint
        public static String b = "b";
        @DataPoint
        public static String nullString = null;
        @DataPoint
        public static String emptyString = "";
    }
    

    最佳答案

    要考虑的一件事:测试对象是否符合平等契约(Contract)应包括其他类型的实例。特别是,子类或父类(super class)的实例可能会出现问题。约书亚·布洛赫(Joshua Bloch)对Effective Java中的相关陷阱做了很好的解释(我正在重复使用达菲(Duffymo)的链接,所以他应该为此感到赞赏)-请参阅“传递性”下涉及Point和ColorPoint类的部分。

    的确,您的实现并不能阻止某人编写涉及子类实例的测试,但是由于ObjectTest是通用类,因此给人的印象是所有数据点都应来自单个类(正在测试的类)。最好完全删除类型参数。值得深思。

    09-30 14:34
    查看更多