繁体   English   中英

对于两个相同的对象,AssertEquals返回false

[英]AssertEquals returning false for two objects which are same

我有两个用户定义的对象,它们的内容相同。 但是assertsEquals反过来equals方法为那些对象返回false。

这是堆栈跟踪,其中也包含对象的toString内容。

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 ....

我对应的类如下。 它具有lombak的@data批注,该批注生成了Equals方法。

@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());
    }

}

我的用户类如下。 这也有@Data Annotation,它生成Equals方法

@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;
    }

}

我的角色类如下:这也有@Data Annotation,它生成Equals方法

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

    @Id
    private Integer roleId;
    private String role;

}

这是我的测试用例,其中包含对象实例化之一。

@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);
        }

其他对象实例化在此代码中发生。

@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);
        }

我不明白为什么两个对象被视为不相等。 如果需要,我想提供更多详细信息。 请帮忙。

提前致谢。

您要比较的两个对象在expiryDate字段中具有不同的值。 您正在使用calculateExpiryDate方法为代码中不同点的两个对象使用new Date()生成它们。 他们将不平等。 请注意,日期精度为毫秒。 我不建议您更改calculateExpiryDate实现以使测试通过,而是可以将expiryDate设置为硬编码的Date值。

Date具有毫秒精度,因此即使两个日期打印相同的值直至秒, equals也可能返回false,因为它们相差毫秒。

您要做的是使用比毫秒更大的粒度。 由于到期时间以分钟为单位,因此您可以将其用作最小时间单位,并将秒/毫秒设置为零。 这是实现这一目标的快速方法。

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调用类VerificationTokenequals方法。 您不会重写此方法,因此将使用Object的默认实现来检查实例是否相等( a == b )。 如果entityCaptor.getValue()不返回原始实例,而是返回序列化或克隆副本,则该测试将失败。

如果您希望返回相同的实例,则应使用assertSame并修复导致返回不同实例的错误。 如果您期望返回其他实例,则应首先执行assertNotSame ,在VerificationToken实现equalshashcode ,并在assertNotSame之后执行assertEquals

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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