equals implementation test coverage junit java - java

I have the first couple if checks in this equals implementation tested in junit but I can't figure out how to get pas the second if check to the final return check. Can someone help me figure this out :) I'll post my two assertions that get me past the first couple if checks. (Laila is my dog an in the code is a Pet object :)).
-- the code to test:
#Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pet pet = (Pet) o;
return Objects.equals(this.id, pet.id) &&
Objects.equals(this.category, pet.category) &&
Objects.equals(this.name, pet.name) &&
Objects.equals(this.photoUrls, pet.photoUrls) &&
Objects.equals(this.tags, pet.tags) &&
Objects.equals(this.status, pet.status);
}
These are the assertions I have that get me past the first two if checks:
assertTrue(laila.equals(laila));
assertFalse(laila.equals(null));

You need to compare with another Pet object that is not the same reference or null.
assertFalse(laila.equals(new Pet(/* instantiate different pet */)));

Related

How can I avoid multiple if else blocks for Object.equals method?

I'm trying to implement this:
public boolean equals(Object o) {
if (o == this) {
return true;
}
if ((null == o) || !(o instanceof Document)) {
return false;
}
Document other = (Document) o;
// compare in a null-safe manner
if (list == null) {
if (other.list != null)
return false;
} else if (other.list == null)
return false;
else if (!(list.size() == other.list.size())
&& !(list.equals(other.list)))
return false;
return true;
where 'list' is a class variable as well as a field of the object 'o'. Please note that the object 'o' has many other fields including booleans and collection too and I need to compare all of them.
I tried finding related answers but most of them recommend switch cases or other Java 8 components which is not relevant to my scenario.
You're greatly complicating things. Writing "equals" is lengthy boring boilerplate, but you're making it even longer.
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Document)) {
return false;
}
Document other = (Document) o;
if (!Objects.equals(list, other.list)) {
return false;
}
return true;
}
All you need per reference field are the three lines above, similarly for primitives (don't forget to handle NaN for floating point).
Your condition is not only much longer, but it also lacks symmetry. This makes it much harder to write and more error-prone.
Anyway, writing "equals" is not something you should do often manually. I recommend using Lombok and there are many more tools, e.g., AutoValue or EqualsBuilder.
A direct rewrite would be:
// compare in a null-safe manner
if (list == null || other.list == null) {
return list == other.list;
} else {
return list.size() == other.list.size() ||
list.equals(other.list));
}
except if the type of list is a standard Java SE List class you can do away with the size() micro-optimization. (A typical `List.equals implementation will do that for you.) So we can rewrite the above as
// compare in a null-safe manner
if (list == null || other.list == null) {
return list == other.list;
} else {
return list.equals(other.list));
}
except that that is what Objects.equals(...) does. So the final rewrite is:
// compare in a null-safe manner
return Objects.equals(list, other.list);
It is unclear if an IDE will generate equals methods test the fields in a null-safe way. But the counterpoint to that is that it is advisable to design your classes so that you don't need to do that. For example, use an empty List rather than a null.

How can I junit test the last block of this equal?

How can I JUnit test the last block of this equal?
Any help would be much appreciated. This is the method in question:
#Override
public boolean equals(java.lang.Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
//unreachable block
ServiceOrderRelationship serviceOrderRelationship = (ServiceOrderRelationship) o;
return Objects.equals(this.id, serviceOrderRelationship.id) &&
Objects.equals(this.href, serviceOrderRelationship.href) &&
Objects.equals(this.relationshipType, serviceOrderRelationship.relationshipType) &&
Objects.equals(this.baseType, serviceOrderRelationship.baseType) &&
Objects.equals(this.schemaLocation, serviceOrderRelationship.schemaLocation) &&
Objects.equals(this.type, serviceOrderRelationship.type) &&
Objects.equals(this.referredType, serviceOrderRelationship.referredType);
}
This is what I've been doing but I can never reach the last block of code inside the equals method:
#Test
public void testEquals() throws Exception {
assertFalse(serviceOrderRelationship.equals(null));
assertTrue(serviceOrderRelationship.equals(serviceOrderRelationship));
assertFalse(serviceOrderRelationship.equals(serviceOrderRelationship1));
}
First of all, thank you all for your responses!
This is how I was able to reach the last block of the equals method. I had to initialize both objects di and di1 and set every variable to the same value, then test the equals condition switching back and forth one variable at a time to a different value. This is an example from another POJO:
// Initialize objects
di.setEdgeId("edgeId");
di.setIdentityEndpoint("identityEndpoint");
di.setUsername("username");
di1.setEdgeId("edgeId");
di1.setIdentityEndpoint("identityEndpoint");
di1.setUsername("username");
// Change value of var and test equal
di1.setEdgeId("edgeIdm");
assertFalse(di.equals(di1));
di1.setEdgeId("edgeId");
// same
di1.setIdentityEndpoint("identityEndpointm");
assertFalse(di.equals(di1));
di1.setIdentityEndpoint("identityEndpoint");
// Same
di1.setUsername("usernamem");
assertFalse(di.equals(di1));
di1.setUsername("username");
// Then at the end perform the other tests
assertTrue(di.equals(di));
assertTrue(di.equals(di1));
assertFalse(di.equals(null));
assertFalse(di.equals(42));
Your problem might be that one of the follow cases, in which the method would return prematurely.
If serviceOrderRelationship and serviceOrderRelationship1 are references to the same object, the true would be returned. Similarly, if they are not of the same type, false would be returned. If serviceOrderRelationship1 is null, false would be returned.
If serviceOrderRelationship is null, then calling equals on it would throw a NullPointerException.

override equals method in User class

I am working on existing project. I have below user class's equals method. when I compare equality with equals I get false on
if (getClass() != other.getClass()) {
return false;
}
The coomplete equals code:
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
User other = (User) obj;
if (getClass() != other.getClass()) {
return false;
}
if (this.getUserId() == null) {
if (other.getUserId() != null) {
return false;
}
} else if (!this.getUserId().equals(other.getUserId())) {
return false;
}
return true;
}
Do I require to check the class type here? If yes, why are my user classes are different? Why can not I put to check class type like below?
if (!(obj instanceof User)){
return false;
}
if (getClass() != other.getClass()) {
return false;
}
This check should be placed before the casting:
User other = (User) obj;
The difference between instanceof and getClass() is that the latter ensures that the type is not a sub-type. So:
User user = new SubUser();
boolean a = user instanceof User;
boolean b = user.getClass() == User.class;
System.out.println(a);
System.out.println(b);
would print:
true
false
You should use the instanceOf method to avoid a ClassCastException later. This Exception will be thrown if you use the equals method with the wrong object type.
First of all, I think you should inverse the lines
User other = (User) obj;
if (getClass() != other.getClass()) {
return false;
}
to become
if (getClass() != other.getClass()) {
return false;
}
User other = (User) obj;
Secondly, the equals method is an important one in the java collections library and in a lot of others as well so you should really think about any implementation details.
Suppose you have an Employee class (with an id) being subclassed into Manager, so you might consider writing an equals method on Employee just checking the id and you are fine. But, are you ? It depends.
So if you check in employee equals method it will return true if you pass a manager. But if you check on class equality by using getClass, it will return false when you pass a manager.
Suppose these 2 classes are stored in a database into an employee table and into a manager table respectively, the database has the id as a column which is defined as as an autoincrement column. Which means you can have an employee with id 100 who is a totally different person than a manager with id 100.
On the other hand you can have a single employee table storing all employees and managers. Hence here if you have an employee object with id 100 and a manager with id 100 then they must be the same person.
For your question, you should put
getClass() != other.getClass()
before
User other = (User) obj;
Equqality is an interesting question. And many people discussed about it. One detail dicussion on equality can be seen in Programming in Scala 2nd Chapter30.
The Effective Java book by Joshua Bloch provides very good suggestions to implement many, what one might consider, standard situations. It includes an approach to implementing the equals method.
Here is a modified implementation:
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof User)) { // this covers the null check
return false;
}
User other = (User) obj; // this is now safe
if ((this.getUserId() == null) && other.getUserId() != null) {
return false
} else if ((this.getUserId() != null) && !this.getUserId().equals(other.getUserId())) {
return false;
}
return true;
}
It is not so obvious, but the instanceof check returns false for null values simply because there is no way identify their type (i.e. nulls are untyped).
As I found, User class from hibernate layer/DAO is not a direct User class. It's sub class of User or a proxy. So, When I check with obj.getClass() it gives false.
In such cases, better not comparing with getClass().
I checked with instanceof.
here you stated that you don't have any subclasses of User so you can use instanceof check.

Java: howto write equals() shorter

I get headaches when I have to write nearly 10 lines of code to say 2 Objects are equal, when their type is equal and both's attribute is equal. You can easily see that in this way of writing the number of lines increase drastically with your number of attributes.
public class Id implements Node {
private String name;
public Id(String name) {
this.name = name;
}
public boolean equals(Object o) {
if (o == null)
return false;
if (null == (Id) o)
return false;
Id i = (Id) o;
if ((this.name != null && i.name == null) || (this.name == null && i.name != null))
return false;
return (this.name == null && i.name == null) || this.name.equals(i.name);
}
}
Google's guava library has the Objects class with Objects#equal that handles nullness. It really helps get things smaller. With your example, I would write:
#Override public boolean equals(Object other) {
if (!(other instanceof Id)) {
return false;
}
Id o = (Id) other;
return Objects.equal(this.name, o.name);
}
The documentation is here.
Also note that there is Objects#hashCode and Objects#toStringHelper to help with hashCode and toString as well!
Please also see Effective Java 2nd Edition on how to write equals().
If you use Eclipse, click "Source" -> "generate hashCode() and equals()". There're many options to create equals() automatically.
There are libraries that'll do it for you. For example, commons-lang has EqualsBuilder
Also, these two lines appear to do the same thing:
if (o == null)
return false;
if (null == (Id) o)
return false;
Maybe you meant this:
if (o == null)
return false;
if (this == o)
return true;
Project Lombok also has a equals and hashCode generator using the #EqualsAndHashCode annotation which has the advantage of being in sync with the current class/source code. I'm not sure about the implementation details but definitely worth looking into if you need to cut down the cruft.
A simpler way (other than generating the code) might be.
public boolean equals(Object o) {
return o instanceof Id
&& (name == null ? ((Id)o).name == null : name.equals(((Id)o).name);
}

An efficient equals(Object o) implementation

I read this SO post after I wrote out the title but still decided to go through with the question on bug-proof implementations of equals in Java. This is my normal implementation
#Override
public boolean equals(Object o){
if(o == null) return false;
if(o instanceof CompositePk == false) return false;
if(this == o) return true;
CompositePk that = (CompositePk)o;
return new EqualsBuilder().append(this.id, that.id)
.append(this.bucketId, that.bucketId)
.isEquals();
}
using Apache's EqualsBuilder to do the mundane stuff. Even easier than this is my Netbean's automatically generated equals(o) implementation
#Override
public boolean equals(Object obj){
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final TemplatesWrapper other = (TemplatesWrapper) obj;
if (this.timeAdded != other.timeAdded && (this.timeAdded == null || !this.timeAdded.equals(other.timeAdded))) {
return false;
}
return true;
}
I take these from 2 diff projects but they both try to accomplish the same thing but using diff approaches. Which style would you rather or are there any flaws you spot?
First of all, there's no need to test for null, then test for instanceof, since foo instanceof Bar evaluates to false when foo is null.
It's weird to compare the result of the instanceof operator to false, since instanceof is a boolean operation.
Comparing classes with getClass() is at best controversial. Joshua Bloch, who wrote much of the Java collections framework and a lot of other important stuff besides, says
This technique ("getClass-based equals
methods") does satisfy the equals
contract, but at great cost. The
disadvantage of the getClass approach
is that it violates the "Liskov
Substitution Principle," which states
(roughly speaking) that a method
expecting a superclass instance must
behave properly when presented with a
subclass instance. If a subclass adds
a few new methods, or trivially
modifies behavior (e.g., by emitting a
trace upon each method invocation),
programmers will be surprised when
subclass and superclass instances
don't interact properly. Objects that
"ought to be equal" won't be, causing
programs to fail or behave
erratically. The problem is
exacerbated by the fact that Java's
collections are based on the equals
method.
You should use instanceof instead of comparing via getClass() unless you have some specific technical reason not to.
After establishing that the other object is comparable to this, you then compare primitives with == and objects with equals. It's more complicated if any of your member objects can be null; you must then write verbose clauses to compare possibly null things to each other (or write a bothNullOrEqual(Object a, Object b) method).
The EqualsBuilder approach looks bogus to me, but that's just a "smell", which I won't argue against technically. In general, I don't like extra method calls in a method that may be called frequently.
The Apache one is bogus because it tests for null and uses the getClass() comparison.
Here's mine:
#Override
public boolean equals(final Object o) {
if (!(o instanceof MyClass))
return false;
final MyClass om = (MyClass)o;
// compare om's fields to mine
}
I would do it this way:
public boolean equals(Object ob) {
if (ob == null) return false;
if (ob == this) return true;
if (!(ob instanceof MyClass)) return false; // OR
if (ob.getClass() != getClass()) return false;
// check relevant members
}
The two lines in the middle are different. One allows for subclasses to be equal (the first one), the other doesn't. Use whichever one is appropriate.
To give you an example, Java's AbstractList class will probably use the second form, because the exact implementation of List is irrelevant. what matters is if the members are equal and in the same position.
Conversely, a Person class should use the first form (instanceof) because if there is a Student subclass and you call Person.equals(Student) it may return true without checking the extra fields in Student whereas Student.equals(Person) will probably return false. If equals() isn't commutative, you're asking for trouble.
I tend to use equals() methods generated by my IDE (IntelliJ IDEA) rather than creating an unnecessary dependency to some Apache library for little gain.
Apache's is better than yours or cletus'.
As far as my vague memory suggests, there is a problem with using instanceof in equals; I can't quite put my finger on why yet, perhaps someone will elaborate. I could be wrong.
-- Edit:
As Chris and Steve helpfully explain below, I was thinking of the "symmetric property" of equals implementation. On this basis, I can back up my claim of prefering the Apache implementation :)
Honestly, the less code you have to write, the better off you are (in most cases).
The code that's generated has been debugged and used by many MANY people. You might as well use what's generated (and if you need to enhance the performance, do so).
The advantage of using the generated code: any time your instance fields changes (and this generated code wasn't modified), you can simply regenerate code.
Sometimes, it's easier to think about maintainability. Rule of thumb: the less code you write yourself, the less you have to debug. If the generated code doesn't take a huge performance hit, generate it!
Explanation: When overriding the equals method, the hashCode() method must be overrided too. So, considering a class with 3 properties as show below and considering that all the properties are significant to equality, the equals() implementation must test all these fields. The order of conditionals isn't important, but all the fields must to be tested for equality to consider the equality between objects at all.
public class SampleClass {
private Long id;
private String description;
private Date creation;
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((creation == null) ? 0 : creation.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
boolean isEquals = true;
if (this == obj) { isEquals = true; }
else if (obj == null) { isEquals = false; }
else if (getClass() != obj.getClass()) { isEquals = false; }
else {
SampleClass other = (SampleClass) obj;
if (creation == null) {
if (other.creation != null) isEquals = false;
} else if (!creation.equals(other.creation)) {
isEquals = false;
} else if (description == null) {
if (other.description != null) isEquals = false;
} else if (!description.equals(other.description)) {
isEquals = false;
} else if (id == null) {
if (other.id != null) isEquals = false;
} else if (!id.equals(other.id)) {
isEquals = false;
}
}
return isEquals;
}

Categories

Resources