简体   繁体   中英

AssertEquals returning false for two objects which are same

I have two user defined objects whose contents are same. But assertsEquals inturn equals method returns false for those objects.

here is the stack trace which contains objects' toString contents as well.

java.lang.AssertionError: expected: com.xyz.test.model.VerificationToken<VerificationToken(id=null, token=, user=User(userId=null, username=null, email=null, password=null, isActive=0, roles=null, imageLocation=null, enabled=false, isAccountNonLocked=true), expiryDate=Sat Dec 22 22:48:49 IST 2018)> but was: com.xyz.test.model.VerificationToken<VerificationToken(id=null, token=, user=User(userId=null, username=null, email=null, password=null, isActive=0, roles=null, imageLocation=null, enabled=false, isAccountNonLocked=true), expiryDate=Sat Dec 22 22:48:49 IST 2018)>
    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotEquals(Assert.java:834)
    at org.junit.Assert.assertEquals(Assert.java:118)
    at org.junit.Assert.assertEquals(Assert.java:144)
    at ....

My corresponding class is as follows. This has lombak's @data annotation which generates Equals method.

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class VerificationToken implements Serializable{
    /**
     * 
     */
    private static final long serialVersionUID = 8788934708305097680L;

    private static final int EXPIRATION = 60 * 24;

    @Id
    private Long id;

    private String token;

    private User user; 

    private Date expiryDate;

    public Date calculateExpiryDate(int expiryTimeInMinutes) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(Calendar.MINUTE, expiryTimeInMinutes);
        return new Date(cal.getTime().getTime());
    }

}

My User class is as follows. This also has @Data Annotation which is generates Equals method

@Entity
@Table(name = "user")
@Data
public class User implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -6480423780555564185L;

    @Id
    private Integer userId;
    private String username;
    private String email;
    @JsonIgnore
    private String password;

    private int isActive;

    private Set<Role> roles;
    private String imageLocation;   
    private boolean enabled;
    private boolean isAccountNonLocked;

    public User() {
        super();
        this.enabled=false;
        this.isAccountNonLocked= true;
    }

    public User(User user) {
        this.username = user.getUsername();
        this.password = user.getPassword();
        this.isActive = user.getIsActive();
        this.roles = user.getRoles();
        this.imageLocation=user.getImageLocation();
        this.enabled= user.enabled;
        this.isAccountNonLocked = user.isAccountNonLocked;
    }

}

My role class is as follows: This also has @Data Annotation which is generates Equals method

@Entity
@Table(name = "role")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {

    @Id
    private Integer roleId;
    private String role;

}

This is my test case which contains one of the objects instantiation.

@Test
        public void testCreateVerificationToken() {
            User user = new User();
            String token = new String();
            VerificationToken myToken = new VerificationToken();
            myToken.setToken(token);
            myToken.setUser(user);
            myToken.setExpiryDate(myToken.calculateExpiryDate(24*60));
            ArgumentCaptor<VerificationToken> entityCaptor = ArgumentCaptor.forClass(VerificationToken.class);
            when(mocktokenRepository.save(entityCaptor.capture())).thenReturn(myToken);
            verificationTokenServiceImpl.createVerificationToken(user, token);

            assertEquals(entityCaptor.getValue(),myToken);
        }

the other object instantiation happens in this code.

@Override
        public void createVerificationToken(User user, String token) {
            VerificationToken myToken = new VerificationToken();
            myToken.setToken(token);
            myToken.setUser(user);
            myToken.setExpiryDate(myToken.calculateExpiryDate(24*60));
            tokenRepository.save(myToken);
        }

I am not able to understand why two objects are considered as not equal. I would love to give more details if needed. Please help.

Thanks in advance.

The two objects you are comparing have different value in expiryDate field. You are generating them using new Date() for both the objects at different point in your code using calculateExpiryDate method. They won't be equal. Note that precision of date is milliseconds. I won't suggest you to change calculateExpiryDate implementation for a test to pass, instead you can set expiryDate to a hardcoded Date value.

Date has millisecond precision, so even if two dates print the same value down to the second, equals might return false because they differ by milliseconds.

What you want to do is use a larger granularity than milliseconds. Since your expiry time is in minutes, you can use that as your minimum time unit and set seconds/milliseconds to zero. Here's a quick way to acheive that.

public Date calculateExpiryDate(int expiryTimeInMinutes) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(new Date());
    cal.add(Calendar.MINUTE, expiryTimeInMinutes);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}

assertEquals calls the equals method of class VerificationToken . You don't override this method so Object 's default implementation is used that is checking instance equality ( a == b ). If entityCaptor.getValue() doesn't return the original instance but eg a serialized or cloned copy, that test will fail.

If you expect the same instance to be returned you should use assertSame and fix the bug that lead to the return of a different instance. If you expect a different instance being returned, you should first do an assertNotSame , implement equals and hashcode in VerificationToken and do the assertEquals after assertNotSame .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM