A.Khan
A.Khan

Reputation: 73

Junit with new Date()

What would the junit test be when i have the following method:

@Override
public void saveLastSuccesfullLogin(final User user) {
    gebruiker.setLastLogin(new Date());
    storeUser(user);
}

submethode storeUser:

@Override
public void storeUser(final User user) {
    EntityManager em = emf.createEntityManager();

    em.getTransaction().begin();
    em.merge(user);
    em.getTransaction().commit();

    em.close();
}

The problem i have is the date, being set for the entity user and then stored. Im using junit and easymock.

Upvotes: 7

Views: 5868

Answers (4)

k.chao.0424
k.chao.0424

Reputation: 1191

You can also create a getDate method, and a date static var:

    private static Date thisDate = null;

    @Override
    public void saveLastSuccesfullLogin(final User user) {
        gebruiker.setLastLogin(getDate());
        storeUser(user);
    }

    public Date getDate() {
        if(thisDate != null) return thisDate;
        return new Date();
    }

    public void setDate(Date newDate) {
        thisDate = newDate;
    }

Then in your test method, you can go ahead and call setDate to control what date you will get.

Upvotes: 0

Neovibrant
Neovibrant

Reputation: 757

There is also a more "enterprise" approach that may be used where Dependency Injection is available (like in EJB, Spring etc.).

You can define an interface, for example TimeService and add e method that returns the current date.

  public interface TimeService {
    Date getCurrentDate();
  }

You can implement this to return new Date() and use it like this:

  gebruiker.setLastLogin(timeService.getCurrentTime());

This will obviously be very easy to test because you can mock the TimeService. Using EasyMock (just an example), this might be:

  Date relevantDateForTest = ...
  expect(timeService.getCurrentTime()).andReturn(relevantDateForTest);
  replay(timeService);

Using the TimeService throughout the entire code and never using new Date() is a pretty good practice and has other advantages as well. I found it helpful in a number of occasions, including manual functional testing of features that would activate in the future. Going even further, the system time may be retrieved from an external system thus making it consistent across clusters etc.

Upvotes: 0

Vinod R
Vinod R

Reputation: 1216

Try pulling the new Date() into a method with default access specifier like below

@Override
public void saveLastSuccesfullLogin(final User user) {
    gebruiker.setLastLogin(getDate());
    storeUser(user);
}
Date getDate() {
    return new Date();
}

In your test class override the class as below using a mock or stubbed date.

<ClassUnderTest> classUnderTest = new <ClassUnderTest> () {
  @Override 
  Date getDate() {
    return mockDate;
  } 
}

In this way you can assert the date value easily as it is going to be stubbed out.

Upvotes: 4

Jeanne Boyarsky
Jeanne Boyarsky

Reputation: 12266

What's the problem with the Date? That you don't know what it is to assert later? A few alternatives:

  1. Pass the date into the method
  2. Create a factory to get the current date/time so you can mock it out
  3. Assert the date within a threshold of correctness

Upvotes: 3

Related Questions