I have a class, User, which acts as the Persistence model for a table of Users in a database:
public class User {
@Id
@Basic(optional = false)
@Column(name = "USER_ID")
private Long userId;
@JoinColumn(name = "LAST_CHANGED_USER_ID", referencedColumnName = "USER_ID")
@ManyToOne(fetch = FetchType.LAZY)
private User lastChangedUser;
...
@Override
public int hashCode() {
int hash = 0;
hash += (userId != null ? userId.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
if (!(object instanceof User)) {
return false;
}
User other = (User) object;
if ((this.userId == null && other.userId != null) ||
(this.userId != null && !this.userId.equals(other.userId))) {
return false;
}
return true;
}
@Override
public String toString() {
return "User[userId=" + userId + "]";
}
}
The field lastChangedUser is updated whenever changes are made to a User instance. Consider the following methods:
private void setUsername(string username, User lastChangedUser){
this.username = username;
this.lastChangedUser = lastChangedUser;
}
public void updateUserName(Long userId, Long lastChangedUserId, String username){
EntityManager em = PersistenceManager.getPersistenceManager()
.getEntityManager();
EntityTransaction transaction = em.getTransaction();
User user = em.find(User.class, userId);
User lastChangedUser = em.find(User.class, lastChangedUserId);
transaction.begin();
user.setUsername(username, lastChangedUser);
transaction.commit();
}
and the unit test:
public void testUpdateUsername(){
UserFacade instance = new UserFacade();
User john = instance.getUserByUserId(new Long(1));
User jane = instance.getUserByUserId(new Long(2));
// make the update and persist
instance.updateUsername("JANE M. DOE", jane.userId, john.userId);
// assert that john made the change to jane
jane = instance.getUserByUserId(new Long(2));
assertTrue(jane.username.equals("JANE M. DOE"));
User actual = jane.lastChangedUser;
User expected = john;
// this assertion passes...
assertTrue(actual.equals(expected));
// yet this assertion fails!
assertTrue(expected.equals(actual));
// this fails as well.
assertEquals(expected, actual);
}
Using Netbeans 7.1.1, the test results screen returns the error message:
FAILED: expected: User[id=1], but was: User[id=1].
Upon inspection, the object actual is not of type User, but that of a Proxy object. I assume this is due to the LAZY fetch annotation. As such, the object's userid has a value of null and expected.equals(actual) returns false. Yet, actual.equals(expected) returns true. To add to my confusion, the failure message shows that actual.userId is not null, but equal to the expected id!
What quirk of Hibernate or JUnit is causing the actual User object to appear after failure?