0

I have:

List<SlaveEntityDTO> result = Jsoner.JsonToSlaveEntityDTO(json);
List<SlaveEntityDTO> result1 = entitiesDTOList;

The result and result1 has the same values for their fields:

enter image description here

When I run Assert.assertEquals(result, result1); I am getting the following message:

java.lang.AssertionError: 
Expected :[core.dto.SlaveEntityDTO@6be46e8f, core.dto.SlaveEntityDTO@3567135c]
Actual   :[core.dto.SlaveEntityDTO@327471b5, core.dto.SlaveEntityDTO@4157f54e]

So how can I compare the values of the fields inside result and result1, instead of comparing if an object is that object?

The SlaveEntityDTO is like this:

public class SlaveEntityDTO extends BaseEntityDTO<SlaveEntity> {

    private String ip;
    private String macAddress;
    private String status;

    private List<PositionEntity> positions;

    @Override
    public SlaveEntity convertToEntity() {
        return new ModelMapper().map(this, SlaveEntity.class);
    }
}

And the BaseEntityDTO is like this:

public abstract class BaseEntityDTO<T> implements Serializable{

    private long id;

    public abstract T convertToEntity();
}
Cristian
  • 1,590
  • 5
  • 23
  • 38
  • 3
    Have you overwritten the equals method for SlaveEntityDTO? – Compass Oct 14 '16 at 20:43
  • See my answer: it seems that you either haven't implemented `equals` for SlaveEntityDTO or you have implemented it incorrectly. If you can show us the source code for your class, I will edit my answer to suggest how to fix it. – nasukkin Oct 14 '16 at 20:46

2 Answers2

3

Your test looks fine. The List interface defines the behavior of its equals, and your debugger shows that ArrayList is being used. ArrayList is a good guy, so we can assume that its implementation of equals is legit.

Thus, we can conclude that your SlaveEntityDTO class either does not override Object#equals(Object) or that it does so in a way that you aren't accounting for (which possibly means that it is implementing it incorrectly).

You can fix this by Overriding equals in BaseEntityDTO. This will give basic behavior of equals to every subclass.

@Override
public boolean equals(Object o) {
    if (this == o) return true; // literally the same object.

    if (o == null || getClass() != o.getClass()) return false; // Not correct type.

    BaseEntityDTO that = (BaseEntityDTO) o;
    return this.id == null ? that.id == null : this.id.equals(that.id);
}

And don't forget: hashCode() MUST match the implementation of equals!

@Override
public int hashCode() {
    return id == null ? 0 : id.hashCode();
}
nasukkin
  • 2,460
  • 1
  • 12
  • 19
  • Note that there are [different schools of thought](http://stackoverflow.com/questions/596462/any-reason-to-prefer-getclass-over-instanceof-when-generating-equals) on whether to use `getClass()` or `instanceof` for type comparison. – shmosel Oct 14 '16 at 20:57
  • @shmosel Understood. However, the way that I posted is consistent with how IntelliJ auto-implements an equals method to date. I defer to their (IntelliJ's developers) wisdom/preference for the purpose of this post :) – nasukkin Oct 14 '16 at 21:02
  • @Cristian Your class definition confirms my suspicions. You need to override `equals` and `hashCode` in your `SlaveEntityDTO` class. Otherwise, you get default equality behavior, which is identity-equality, which is *almost never* what you will want. – nasukkin Oct 14 '16 at 21:04
  • @nasukkin could you please update your answer with the exact solution? I tried to implement the Override equals and Override hashCode and I am doing something wrong. It is the first time that I need to do this. Thank you in advance. – Cristian Oct 14 '16 at 21:12
  • 1
    @Cristian I imagine that what's going wrong is that `id` is a private member of the BaseEntityDTO class, so it's not accessible to the SlaveEntityDTO class. One solution for you would be to implement `equals` and `hashCode` into the base class instead of the sub class. Another solution would be to promote `id` to `protected` visibility. Yet another solution would be to provide a `getId` accessor method and to use that instead of a straight reference to the variable. – nasukkin Oct 14 '16 at 21:17
  • 1
    @Cristian You can't just compare the two ArrayLists like that. Even when you override `equals()` and `hashCode()` you'll have to write some logic to do the comparison! – user2004685 Oct 14 '16 at 21:19
  • Thank you guys. With your comments and answer I understand what is the problem and I am pretty sure that I will resolve the problem. – Cristian Oct 14 '16 at 21:21
0

When I run Assert.assertEquals(result, result1); I am getting the following message:

java.lang.AssertionError: Expected :[core.dto.SlaveEntityDTO@6be46e8f, core.dto.SlaveEntityDTO@3567135c] Actual :[core.dto.SlaveEntityDTO@327471b5, core.dto.SlaveEntityDTO@4157f54e]

As you said, you are getting the error because you are comparing the objects and not the content of the two objects.

One way of doing it would be to convert both the JSON objects to Strings and then compare the two Strings but remember that order in JSON is not fixed and it might happen that your result object has the elements in order {2, 1, 3} but the source object has it in the order {1, 2, 3}.

I think you should try creating Sets out of your source elements and result elements and then compare both the Sets based on their sizes and also elements in it to assert whether the two objects are equal or not.

You can read this post here to know more about JSON comparison:

Community
  • 1
  • 1
user2004685
  • 9,548
  • 5
  • 37
  • 54
  • Converting an object to String and comparing it to another String is a terrible way to do object equality. Also, java.util.List has a fully-formed definition and specification for how it supports its `equals` method, so it should be considered good form to rely upon it. – nasukkin Oct 14 '16 at 21:08
  • @nasukkin I think you misunderstood me. I am not suggesting to convert the object itself to String but to Stringify the JSON and do the comparison. But as I have said it would work for a single element but if there are more elements then it can cause issues as the order in which response is being received is not fixed. – user2004685 Oct 14 '16 at 21:12