Search code examples
javawhitespacejunit4

Junit 4 assertEquals(...) fails to compare two objects


Error message:

Expected: UserDTO<UserDTO{username='user', password='password', email='mail@mail'}> 
Actual: UserDTO<UserDTO{username='user', password='password', email='mail@mail'}>

The only difference is a whitespace after the '>' of the expected stringified object. I do not know why, because i compare two UserDTO objects. Has anyone had the same issue?

UPDATE: The equals implementation of UserDTO.

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        UserDTO userDTO = (UserDTO) o;

        if (username != null ? !username.equals(userDTO.username) : userDTO.username != null) return false;
        if (password != null ? !password.equals(userDTO.password) : userDTO.password != null) return false;
        return  (email != null ? !email.equals(userDTO.email) : userDTO.email != null);

    }

Solution

  • The comparison failure message gives you a state of objects what you expect and what you get.
    The fact that the two objects show the same state but that these are not equals for assertEquals() means that the equals() method doesn't rely on the value of the declared fields or it may also means that equals() contains logic error(s) .

    And for you it is the second case as this :

     return  (email != null ? !email.equals(userDTO.email) : userDTO.email != null);
    

    should be :

    return  (email != null ? email.equals(userDTO.email) : userDTO.email == null);
    

    as if email is not null, you want to return the equals() result on this field while if email is null, you want to return true if other.email == null and false otherwise.

    Anyway, the equals() method could be much simplified by using Objects.equals() to compare each field as it spares you from doing a null check for each field :

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
    
        UserDTO userDTO = (UserDTO) o;
        return (Objects.equal(username, userDTO.username) && Objects.equal(password, userDTO.password) && Objects.equal(email, userDTO.email));        
    }