Arek Jurasz

Software Engineer

equals operator in Groovy

October 27, 2019

If you come from Java land and are lucky enough then you probably write your tests in Spock using Groovy. Then you already know that Groovy allow overriding operators (you can find more about them in docs) and one of them is == which in contrast to Java does not compare objects reference but their equality through equals method.

Let’s assume we have got following Java classes:

public abstract class Event {
	private final timestamp = Instant.now().toEpochMilli();
	
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Event event = (Event) o;
        return timestamp == event.timestamp;
    }

    @Override
    public int hashCode() {
        return Objects.hash(timestamp);
    }	
}

public class ApplicationEvent extends Event {
	private final UUID correlationId;
	
	public ApplicationEvent(UUID correlationId) {
		this.correlationId = correlationId
	}
	
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ApplicationEvent event = (ApplicationEvent) o;
        return corelationId == event.corelationId;
    }

    @Override
    public int hashCode() {
        return Objects.hash(corelationId);
    }	
}

If we would write a test for equality I would look something like this:

class ApplicationEventSpec extends Specification {
	def "should recognize equal objects"() {
		given:
		def correlationId = UUID.randomUUID();
		
		expect:
		new ApplicationEvent(correlationId) == new ApplicationEvent(correlationId) // true
	}
} 

Above test will start failing after implementing Comparable interface on Event class.

public abstract class Event implements Comparable<Event> {
    @Override
    public int compareTo(Event o) {
        return Long.compare(timestamp, o.timestamp);
    }	
	
	// rest of the code from the previous snippet stays as it was
}

Unfortunately, I didn’t figure what is wrong on my own so I had to look for an explanation on the web. In the official documentation I have found the following:

In Groovy == translates to a.compareTo(b)==0, if they are Comparable, and a.equals(b) otherwise.

So there is a single exception for == operator which is useful to know. If it comes to failing test it can be fixed by explicitly calling equals method.

Share This Post