Why does .equals () result in an assertion error when comparing two objects ... but only sometimes?

I am working on unit testing a project in a code school, and .equals() gives me some problems. In my project, .save() stored in the SQL database. This code passes unit test:

 @Test public void save_assignsNameToObject() { Restaurant testRestaurant = new Restaurant("PokPok","503-444-4444"); testRestaurant.save(); Restaurant savedRestaurant = Restaurant.all.get(0); assertEquals(savedRestaurant.getName(), "PokPok"); } 

But if I change the final line to the following, it will result in an assertion error:

 assertTrue(savedRestaurant.equals(testRestaurant)); 

I debugged using System.out.println() to verify that both values ​​in testRestaurant do ".equal" the corresponding values ​​in savedRestaurant . The following unit test (for an object of another, very similar class) passes using the .equals() method:

 @Test public void save_assignsIdToObject_true() { Cuisine testCuisine = new Cuisine("Mexican"); testCuisine.save(); Cuisine savedCuisine = Cuisine.all().get(0); assertTrue(savedCuisine.equals(testCuisine)); } 

Edit: here is my source code for .equals() :

 @Override public boolean equals(Object otherRestaurant) { if (!(otherRestaurant instanceof Restaurant)) { return false; } else { Restaurant newRestaurant = (Restaurant) otherRestaurant; return this.getId() == new Restaurant.getId() && this.getName().equals(newRestaurant.getName()) && ... this.getPhone().equals(newRestaurant.getPhone()); } } 

Why can .equals() compare some objects and not others? In my code example, the only difference I see is that one object takes one parameter and the other takes two.

Thanks!

+6
source share
4 answers

By default, the equals() a Java object checks that they are the same object (and not two objects with the same values). http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29

The String object overrides equals() to provide a version that returns true for two different objects with the same value, but your custom class Restaurant does not.

You can define custom equals() for example.

 public class Restaurant { private String name; private String tel; public Restaurant(String name, String tel) { this.name = name; this.tel = tel; } /*getters and setters*/ override public boolean equals(Object obj) { if(obj instanceOf Restaurant) { Restaurant that = (Restaurant) obj; return (this.name.equals(that.getName()) && this.tel.equals(that.getTel())); } else { return false; } } } 
+3
source

First, compares Strings ( savedRestaurant.getName() ), where, as a second, objects of the Restaurant ( savedRestaurant ) class are compared.

The string has its own implementation of the equals () method.

You need to override the equals method in Restaurant to make the work equal, as you would expect otherwise, it will check if both objects are the same or not the same ( Object.equals () ).


Update:

You have a problem with this line in the equals method

if id long

 this.getId() == newRestaurant.getId() // not new Restaurant.getId() 

if id long

 this.getId().equals(newRestaurant.getId()) // not new Restaurant.getId() 
+1
source

By default, your Restaurant.equals() returns to Object.equals() , which simply compares the identifiers of the objects. It seems you are returning another Restaurant instance when you call Restaurant.all.get(0) . The field values ​​are the same, but this is a different instance of the object.

I do not recommend implementing equals() and hashCode() , because it is quite difficult to do it right and not necessary here. I would just give each class an ID field, usually a long value that appears in the auto-increment field in the database. An identifier uniquely identifies each record in the database. Then in your test, you can simply check if you have an object with the same database id.

The reason the behavior is currently different from Cuisine and Restaurant probably lies in code that you didn't show us. Maybe they use different equals() implementations? Or does the way to save and search them work differently? Maybe Cuisine.get() returns the same instance of the object that was saved, and Restaurant.get() creates a new instance? So that we know that you will need to show the code of both classes.

Do you use the database in memory? How do you store Restaurant and Cuisine data?

+1
source

You need to redefine the equals implementation in your Restaurant class in order to be able to use it with the right meaning to compare objects of this class

The default comparison by default will lead you to a method in the object class that only checks if both objects point to the same link (same address in memory)

+1
source

All Articles