user3276602
user3276602

Reputation: 233

Comparing dates with JUnit testing

Hello I'm new to the site and have a issue with my application using JUnit testing. My issue is when I try to compare the Date method with itself it always fails. I printed the Date object in the test to see the problem and always end up with the package name and random letters. Here is the Date constructor:

public class Date
{
SimpleDateFormat dformat = new SimpleDateFormat("dd-MM-yyyy");

private int day;
private int month;
private int year;

public Date() 
{
    String today;
    Calendar present = Calendar.getInstance();

    day = present.get(Calendar.DAY_OF_MONTH);
    month = present.get(Calendar.MONTH);
    year = present.get(Calendar.YEAR);

    present.setLenient(false);
    present.set(year, month - 1, day, 0, 0);

    today = dformat.format(present.getTime());
    System.out.println(today);
}

Here is my test:

@Test 
public void currentDay()
{
    Date current = new Date();
    System.out.println(current);
    assertEquals("today:", current, new Date());
}

Yet the result always fails and I get something on the lines of:

comp.work.wk.Date@d3ade7

Any help would be appreciated.

Upvotes: 22

Views: 70428

Answers (7)

Thom
Thom

Reputation: 15052

You need to override both equals() and toString(). If you override equals, always override hashcode() so that your maps work properly.

Upvotes: 1

Anonymous
Anonymous

Reputation: 86296

java.time.LocalDate

For production code never create your own Date class (as an exercise it’s fine). Use LocalDate from java.time, the modern Java date and time API.

For example:

    ZoneId zone = ZoneId.of("Africa/Niamey");
    LocalDate current = LocalDate.now(zone);
    System.out.println(current);
    System.out.println("Is equal? " + current.isEqual(LocalDate.now(zone)));

Output when I ran this code just now:

2021-04-07
Is equal? true

If the code happens to run just over midnight so now() is called just before and just after the day changes, then you will get two different dates, and the second line will be Is equal? false.

Since it is never the same date in all time zones, specifying the desired time zone is crucial.

If this was for an exercise

If you are doing an exercise requiring you to write your own date class, then it’s a fine exercise. In this case the answers stating that in your date class you should override equals(), hashCode() and toString() are the correct ones.

In your own date class you should not base its functionality on Calendar nor SimpleDateformat. Calendar is poorly designed, SimpleDateFormat is notoriously troublesome, and both are long outdated. Instead use LocalDate and DateTimeFormatter from java.time.

Tutorial link

Oracle tutorial: Date Time explaining how to use java.time.

Upvotes: 0

Čamo
Čamo

Reputation: 4172

I have this solution to test date order

// date1 has to be before date2
if( !date1.before(date2) ) Assert.fail("Date1 is not before date2");

// date1 has to be before or equals to date2
if( date1.after() ) Asssert.fail("Date1 is after date2")

Upvotes: 0

Basil Bourque
Basil Bourque

Reputation: 338835

Update The Joda-Time project is now in maintenance mode, with the team recommending migration to the java.time classes.


This kind of work is much easier with the Joda-Time library instead of the notoriously troublesome Date/Calendar classes.

Example Code in Joda-Time 2.3

Set up some data…

DateTime now = new DateTime();
DateTime yesterday = now.minusDays( 1 );
DateTime nowAgain = new DateTime( now.toString() ); // New object, but same value inside.

Compare…

boolean isNowEqualToYesterday = now.equals( yesterday );
boolean isNowEqualToNowAgain = now.equals( nowAgain );

Dump to console…

System.out.println( "now: " + now );
System.out.println( "yesterday: " + yesterday );
System.out.println( "nowAgain: " + nowAgain );

System.out.println( "isNowEqualToYesterday: " + isNowEqualToYesterday );
System.out.println( "isNowEqualToNowAgain: " + isNowEqualToNowAgain );

When run…

now: 2014-02-06T01:31:43.157-08:00
yesterday: 2014-02-05T01:31:43.157-08:00
nowAgain: 2014-02-06T01:31:43.157-08:00
isNowEqualToYesterday: false
isNowEqualToNowAgain: true

Convert

You can convert in and out of Joda-Time if need be.

org.joda.time.DateTime dateTime = new DateTime( date ); // From Date to DateTime.
java.util.Date date = dateTime.toDate();  // From DateTime to Date.

Upvotes: 1

Hans Wouters
Hans Wouters

Reputation: 628

Although the answer by @Shrikanth solves it, this issue also arises with normal Date objects. Two possible solutions are given here:

  1. Make use of DateUtils.truncate (or even DateUtils.truncatedEquals) to compare the dates. This is something you could use in your equals method, or for normal Date objects directly in you assertEquals/assertTrue.

    assertEquals(DateUtils.truncate(date1,Calendar.SECOND), 
                 DateUtils.truncate(date2,Calendar.SECOND));
    
  2. Don't check whether the dates are the same, but whether they are close enough to eachother (for JUnit test sake):

    assertTrue("Dates aren't close enough to each other!", 
               Math.abs(date2.getTime() - date1.getTime()) < 1000);
    

Upvotes: 14

Karthik Kota
Karthik Kota

Reputation: 423

Overriding default equals method is not necessary. You simply use Date.compareTo() to compare two date objects.

Upvotes: 14

Srikanth Ganji
Srikanth Ganji

Reputation: 1157

The default equals object compares memory locations. If both objects are pointing to same memory location then only it will print equals which is not the case in your program. since they are pointing to two different memory locations it is always giving false which is expected.

If you feel your assertEquals(date1,date2) method should return true since the contents are equal then you should override the equals method. And when ever you override equals you should override hashcode() method also to ensure that you can confidently use your class instance as a key in any hashing based collection like HashMap or HashSet.

Here is a link explaining how to override equals() and hashcode() method

http://javarevisited.blogspot.in/2011/02/how-to-write-equals-method-in-java.html

And don't name your class same as any API class as Jon Skeet suggested.

Hope this helps.

Upvotes: 7

Related Questions