How do I assert equality on two classes without an equals method?

后端 未结 23 1356
臣服心动
臣服心动 2020-11-28 05:20

Say I have a class with no equals() method, to which do not have the source. I want to assert equality on two instances of that class.

I can do multiple asserts:

相关标签:
23条回答
  • 2020-11-28 05:44

    Mockito offers a reflection-matcher:

    For latest version of Mockito use:

    Assert.assertTrue(new ReflectionEquals(expected, excludeFields).matches(actual));
    

    For older versions use:

    Assert.assertThat(actual, new ReflectionEquals(expected, excludeFields));
    
    0 讨论(0)
  • 2020-11-28 05:44

    Using Shazamcrest, you can do:

    assertThat(obj1, sameBeanAs(obj2));
    
    0 讨论(0)
  • 2020-11-28 05:46

    There is many correct answers here, but I would like to add my version too. This is based on Assertj.

    import static org.assertj.core.api.Assertions.assertThat;
    
    public class TestClass {
    
        public void test() {
            // do the actual test
            assertThat(actualObject)
                .isEqualToComparingFieldByFieldRecursively(expectedObject);
        }
    }
    

    UPDATE: In assertj v3.13.2 this method is deprecated as pointed out by Woodz in comment. Current recommendation is

    public class TestClass {
    
        public void test() {
            // do the actual test
            assertThat(actualObject)
                .usingRecursiveComparison()
                .isEqualTo(expectedObject);
        }
    
    }
    
    0 讨论(0)
  • 2020-11-28 05:47

    Since this question is old, I will suggest another modern approach using JUnit 5.

    I don't like this solution because I don't get the full equality picture if an early assert fails.

    With JUnit 5, there is a method called Assertions.assertAll() which will allow you to group all assertions in your test together and it will execute each one and output any failed assertions at the end. This means that any assertions that fail first will not stop the execution of latter assertions.

    assertAll("Test obj1 with obj2 equality",
        () -> assertEquals(obj1.getFieldA(), obj2.getFieldA()),
        () -> assertEquals(obj1.getFieldB(), obj2.getFieldB()),
        () -> assertEquals(obj1.getFieldC(), obj2.getFieldC()));
    
    0 讨论(0)
  • 2020-11-28 05:47

    Some of the reflection compare methods are shallow

    Another option is to convert the object to a json and compare the strings.

    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;    
    public static String getJsonString(Object obj) {
     try {
        ObjectMapper objectMapper = new ObjectMapper();
        return bjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
         } catch (JsonProcessingException e) {
            LOGGER.error("Error parsing log entry", e);
            return null;
        }
    }
    ...
    assertEquals(getJsonString(MyexpectedObject), getJsonString(MyActualObject))
    
    0 讨论(0)
  • 2020-11-28 05:50

    I generally implement this usecase using org.apache.commons.lang3.builder.EqualsBuilder

    Assert.assertTrue(EqualsBuilder.reflectionEquals(expected,actual));
    
    0 讨论(0)
提交回复
热议问题