Friday 15 April 2016

Mean bean: How to test hashCode method

HashCodeMethodTester class provides testHashCodeMethod method, which verifies that the hashCode method complies with the HashCode Contract.

What is the contract of HashCode?
As per Javadoc, hashCode method should satisfy following points.

a.   Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
b.   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.
c.    It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

I already explained the relation between hashCode and equals method in following post.

Meanbean implements following algorithms to test whether hashCode methos is comply with the HashCode Contract (or) not.


Algorithm
Description
HashCodes Equal test algorithm
create instance of class under test, object x
create instance of class under test, object y
assert x.equals(x)
assert x.hashCode() == y.hashCode()
HashCode Consistent Test Algorithm
create instance of class under test, object x
for i in 1..100 do
         assert hashCode is consistent
end for

public class Employee {
  private String firstName;
  private String lastName;
  private int id;
  private int age;
  private float salary;

  public String getFirstName() {
    return firstName.toUpperCase();
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName.toUpperCase();
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public float getSalary() {
    return salary;
  }

  public void setSalary(float salary) {
    this.salary = salary;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result
        + ((firstName == null) ? 0 : firstName.hashCode());
    result = prime * result + id;
    result = prime * result
        + ((lastName == null) ? 0 : lastName.hashCode());
    result = prime * result + Float.floatToIntBits(salary);
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Employee other = (Employee) obj;
    if (age != other.age)
      return false;
    if (firstName == null) {
      if (other.firstName != null)
        return false;
    } else if (!firstName.equals(other.firstName))
      return false;
    if (id != other.id)
      return false;
    if (lastName == null) {
      if (other.lastName != null)
        return false;
    } else if (!lastName.equals(other.lastName))
      return false;
    if (Float.floatToIntBits(salary) != Float.floatToIntBits(other.salary))
      return false;
    return true;
  }

}

import org.junit.Test;
import org.meanbean.test.HashCodeMethodTester;

public class TestBean {

  @Test
  public void testEmployee() {
    HashCodeMethodTester tester = new HashCodeMethodTester();
    tester.testHashCodeMethod(Employee.class);
  }

}


You can also call testHashCodeMethod by passing EquivalentFactory instance.
import org.junit.Test;
import org.meanbean.lang.EquivalentFactory;
import org.meanbean.test.HashCodeMethodTester;

public class TestBean {

  @Test
  public void testEmployee() {
    HashCodeMethodTester tester = new HashCodeMethodTester();
    tester.testHashCodeMethod(new EmployeeFactory());
  }

  public class EmployeeFactory implements EquivalentFactory<Employee>{

    public Employee create() {
      Employee emp = new Employee();
      
      emp.setAge(26);
      emp.setFirstName("sudhir");
      emp.setId(1234);
      emp.setLastName("Sami");
      emp.setSalary(1234567);
      return emp;
    }
    
  }
}







Previous                                                 Next                                                 Home

No comments:

Post a Comment