About

testUtils is a simple set of utilities aimed at helping you test and improve the coverage of your code. For the time being it is only comprised of BeanLikeTester.

BeanLikeTester

This class provides methods to easily and quickly test and improve the test coverage of 'bean like' objects (i.e. objects with setters and getters but that don't necessarily implement the Serializable interface and can have non default constructors).

The beanLike objects:

  • have a default constructor and/or constructors that only initialise properties,
  • have optional setters (setXXX()),
  • have accessors (isXXX(), getXXX()) for all the properties,
  • properties are either readonly or set by a either a constructor or a setter (or both).

All the initial values, setters, getters, non default constructors, hashCode(), equals(), toString() can be automatic tested from a map of default and non default property/value.

How to use it

For example to test this simple bean:

public class MyBean {
 
    private String  property1 = "defaultValue"; // Read/write.
    private boolean property2;                  // Read/write.
    private long    property3 = -1;             // Read only.
 
    public String getProperty1() {
        return property1;
    }
 
    public void setProperty1(String property1) {
        this.property1 = property1;
    }
 
    public boolean isProperty2() {
        return property2;
    }
 
    public void setProperty2(boolean property2) {
        this.property2 = property2;
    }
 
    public long getProperty3() {
        return property3;
    }
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((property1 == null) ? 0 : property1.hashCode());
        result = prime * result + (property2 ? 1231 : 1237);
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MyBean other = (MyBean) obj;
        if (property1 == null) {
            if (other.property1 != null)
                return false;
        }
        else if (!property1.equals(other.property1))
            return false;
        if (property2 != other.property2)
            return false;
        return true;
    }
 
    @Override
    public String toString() {
        return "MyBean [property1=" + property1 + ", property2=" + property2 + ", property3=" + property3 + "]";
    }

you would use instances of PropertiesAndValues and BeanLikeTester to:

// 1. Define the default values expected:
PropertiesAndValues defaultValues = new PropertiesAndValues();
defaultValues.put("property1", "defaultValue");
defaultValues.put("property2", false);
defaultValues.put("property3", -1L);
 
// 2. Give another value for each of the properties:
PropertiesAndValues otherValues = new PropertiesAndValues();
otherValues.put("property1", "anotherValue");
otherValues.put("property2", true);
otherValues.put("property3", 0L);
 
// 3. Create the tester:
BeanLikeTester blt = new BeanLikeTester(MyBean.class);
 
// 4a. Test the bean's methods:
blt.testDefaultValues(defaultValues);
blt.testMutatorsAndAccessors(defaultValues, otherValues);
blt.testEqualsAndHash(defaultValues, otherValues);
blt.testToString(defaultValues, otherValues);
 
// 4b. Or test everything at once.
blt.testBeanLike(defaultValues, otherValues);
 
// 5. Check the code coverage. The method equals() may not have been totally covered.
// In this case create another set of values and run testEqualsAndHash() against it:
otherValues.put("property1", null);
otherValues.put("property2", true);
otherValues.put("property3", 0L);
blt.testEqualsAndHash(defaultValues, otherValues);
 
// If any of the tests fails or the values given in parameter are incorrect an
// exception BeanLikeTesterException is thrown.

Now, if you want to test an object that defines non default constructors that only set properties, e.g.:

public final class MyBeanLike {
    private final String       property1;                      // Can only be set by a constructor.
    private int                property2;                      // Can be set by either a constructor or a setter.
    private boolean            property3;                      // Can only be set by a setter.
    private final Integer      property4  = Integer.MAX_VALUE; // get only.
 
    public MyBeanLike(String property1) {
        this.property1 = property1;
    }
 
    public MyBeanLike(String property1, int property2) {
        this.property1 = property1;
        this.property2 = property2;
    }
 
    public String getProperty1() {
        return property1;
    }
 
    public int getProperty2() {
        return property2;
    }
 
    public void setProperty2(int property2) {
        this.property2 = property2;
    }
 
    public boolean isProperty3() {
        return property3;
    }
 
    public void setProperty3(boolean property3) {
        this.property3 = property3;
    }
 
    public Integer getAReadOnlyProperty() {
        return property4;
    }
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + (property3 ? 1231 : 1237);
        result = prime * result + ((property1 == null) ? 0 : property1.hashCode());
        result = prime * result + property2;
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof MyBeanLike)) {
            return false;
        }
        final MyBeanLike other = (MyBeanLike) obj;
        if (property3 != other.property3) {
            return false;
        }
        if (property1 == null) {
            if (other.property1 != null) {
                return false;
            }
        }
        else if (!property1.equals(other.property1)) {
            return false;
        }
        if (property2 != other.property2) {
            return false;
        }
        return true;
    }
}

you would first use ConstructorSignatureAndPropertiesMapping to Define the mapping between the constructors' signatures and the properties and then follow the same steps. E.g.:

// 1. Define the mapping between the constructors' signatures and the properties:
ConstructorSignatureAndPropertiesMapping mapping = new ConstructorSignatureAndPropertiesMapping();
List<Class<?>> signature1 = Arrays.<Class<?>> asList(String.class);
mapping.put(signature1, Arrays.asList("property1"));
 
List<Class<?>> signature2 = Arrays.<Class<?>> asList(String.class, int.class);
mapping.put(signature2, Arrays.asList("property1", "property2"));
 
// 2. Define the default values expected:
PropertiesAndValues defaultValues = new PropertiesAndValues();
defaultValues.put("property1", null);
defaultValues.put("property2", 0);
defaultValues.put("property3", false);
defaultValues.put("aReadOnlyProperty", Integer.MAX_VALUE);
 
// 3. Give another value for each of the properties:
PropertiesAndValues otherValues = new PropertiesAndValues();
otherValues.put("property1", "aNewString");
otherValues.put("property2", 3);
otherValues.put("property3", true);
// 'property4' is a read only property and can be omitted here.
 
// 4. Create the tester:
BeanLikeTester blt = new BeanLikeTester(MyBeanLike.class, mapping);
 
// 5. Test the object:
blt.testBeanLike(defaultValues, otherValues);