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

后端 未结 23 1372
臣服心动
臣服心动 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:51

    The library Hamcrest 1.3 Utility Matchers has a special matcher that uses reflection instead of equals.

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

    You can use Apache commons lang ReflectionToStringBuilder

    You can either specify the attributes you want to test one by one, or better, exclude those you don't want:

    String s = new ReflectionToStringBuilder(o, ToStringStyle.SHORT_PREFIX_STYLE)
                    .setExcludeFieldNames(new String[] { "foo", "bar" }).toString()
    

    You then compare the two strings as normal. For the point about reflection being slow, I assume this is only for testing, so shouldn't be so important.

    0 讨论(0)
  • 2020-11-28 05:54

    You can use reflection to "automate" the full equality testing. you can implement the equality "tracking" code you wrote for a single field, then use reflection to run that test on all fields in the object.

    0 讨论(0)
  • 2020-11-28 05:54

    I had the exact same conundrum when unit testing an Android app, and the easiest solution I came up with was simply to use Gson to convert my actual and expected value objects into json and compare them as strings.

    String actual = new Gson().toJson( myObj.getValues() );
    String expected = new Gson().toJson( new MyValues(true,1) );
    
    assertEquals(expected, actual);
    

    The advantages of this over manually comparing field-by-field is that you compare all your fields, so even if you later on add a new field to your class it will get automatically tested, as compared to if you were using a bunch of assertEquals() on all the fields, which would then need to be updated if you add more fields to your class.

    jUnit also displays the strings for you so you can directly see where they differ. Not sure how reliable the field ordering by Gson is though, that could be a potential problem.

    0 讨论(0)
  • 2020-11-28 05:54

    You can override the equals method of the class like:

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (app != null ? app.hashCode() : 0);
        return hash;
    }
    
    @Override
    public boolean equals(Object object) {
        HubRule other = (HubRule) object;
    
        if (this.app.equals(other.app)) {
            boolean operatorHubList = false;
    
            if (other.operator != null ? this.operator != null ? this.operator
                    .equals(other.operator) : false : true) {
                operatorHubList = true;
            }
    
            if (operatorHubList) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
    

    Well, if you want to compare two object from a class you must implement in some way the equals and the hash code method

    0 讨论(0)
  • I know it's a bit old, but I hope it helps.

    I run into the same problem that you, so, after investigation, I found few similar questions than this one, and, after finding the solution, I'm answering the same in those, since I thought it could to help others.

    The most voted answer (not the one picked by the author) of this similar question, is the most suitable solution for you.

    Basically, it consist on using the library called Unitils.

    This is the use:

    User user1 = new User(1, "John", "Doe");
    User user2 = new User(1, "John", "Doe");
    assertReflectionEquals(user1, user2);
    

    Which will pass even if the class User doesn't implement equals(). You can see more examples and a really cool assert called assertLenientEquals in their tutorial.

    0 讨论(0)
提交回复
热议问题