Jerry
Jerry

Reputation: 1197

Kotlin class instance assert not correct

I'm converting a Java project into Kotlin. I've converted a User object into Kotlin and when I run the existing JUnit tests in Java I'm getting a error between two instances of the Kotlin User object.

User.kt:

data class User (
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
var id: Long? = null,
...
)

TestUtil.java

import static org.assertj.core.api.Assertions.assertThat;

public class TestUtil {
    public static void equalsVerifier(Class clazz) throws Exception {
        Object domainObject1 = clazz.getConstructor().newInstance();
        // Test with an instance of the same class
        Object domainObject2 = clazz.getConstructor().newInstance();
        assertThat(domainObject1).isNotEqualTo(domainObject2);
    }
}

The assertThat(domainObject1).isNotEqualTo(domainObject2) test fails, as I believe in Java comparison is not done correctly on the Kotlin class. If I run this through a debugger, I can see that domainObject1 and domainObject2 are different instances.

Is it possible to get this test case to pass? The same test case is used for other Java classes, so it has to work for both Java and Kotlin classes.

Upvotes: 1

Views: 3023

Answers (2)

BakaWaii
BakaWaii

Reputation: 6992

In Kotlin, equals() is generated automatically for data class to check for equality of the properties.

Quote from "Kotlin in Action":

The generated equals() method checks that the values of all the properties are equal. ... Note that properties that aren’t declared in the primary constructor don’t take part in the equality checks and hashcode calculation.

If you want to pass the test case without modifying it, you may override equals() of your data class to check for referential equality.

override fun equals(other: Any?) = this === other

Note that it may affect your other code, if there is any function which relies on structural equality of your data class. So, I suggest that you refer to @shawn's answer to change your test case instead.

Upvotes: 1

shawn
shawn

Reputation: 4363

The isNotEqualTo calls equals. The Kotlin class implements correct equals method for data class. So domainObject1.equals(domainObject2) is true. This behavior is correct.

just look at the AssertJ document:

isNotSameAs(Object other): 
   Verifies that the actual value is not the same as the given one, 
   ie using == comparison.

I think you should try:

    assertThat(domainObject1).isNotSameAs(domainObject2);

Upvotes: 1

Related Questions