Question

I'm mocking a method with easymock that has a date in its body, something like this:

public void testedMethod() {
    ...
    if (doSomething(new Date())) {
    ...
}

And my test looks like this:

public void testThatMethod() {
    ...
    expect(testedClass.testedMethod(new Date())).andReturn(false);
    ...
}

But when I run the test sometimes I get an error like this:

Unexpected method call testedMethod(Thu Jan 28 09:45:13 GMT-03:00 2010): testedMethod(Thu Jan 28 09:45:13 GMT-03:00 2010): expected: 1, actual: 0

I think that it's because sometimes the date has a slightly difference. I've tried the some flexible expectations without success. Is there a way to get around this?

Was it helpful?

Solution

Stop using new Date(), use a Calendar with constant time instead.

//Declare the Calendar in your test method
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(0l);

//receive the calendar to be used in testedClass constructor
public void testedMethod() {
    ...
    if (doSomething(cal.getTime())) {
    ...
}

//use the same calendar to make the assertion
public void testThatMethod() {
    ...
    expect(testedClass.(testedMethod(cal.getTime())).andReturn(false);
    ...
}

OTHER TIPS

We're constantly facing similar issues and these are the alternatives I see:

  1. Provide the date as a parameter to the method (+) Quick change (-) a bit dirty - when you just want to use "now", it also pollutes your interface
  2. Pull the date in from a collaborator "QueryCurrentDateProvider" (+) Still pretty quick (+) Can also be mocked -> you are sure you use the same date (-) unnecessary collaborators created for every service where you need to do something similar
  3. Write your own EasyMock argument matcher where you abstract to what you actually want to do - when you're just interested in the day, not the time you can use something like commons DateUtils.isSameDay to get this to run (+) cleanest solution (+) no change to your productive code (-) you have to write your own matcher (although I don't understand why EasyMock doesn't already have that)
  4. Move the "new Date()" to a private method, then mock this method with something like PowerMock (+) quick (+) small change to the productive code (-) introduce power mock as a dependency
  5. Change the parameter from Date to String and use a common pattern to transform the date to a string prior to calling the method (+) quick (+) no additional code, libraries required on the testing site (-) you have to format the date before calling the method and parse the date in the called method

So it really comes up to your personal liking. When you're working with current timestamps a lot I would recommend the argument matcher - since this investment will pay off quickly.

I just found this thread and it helped me solve a problem I was stuck at for a good hour.

Thought I'd share my 2 cents:

If you don't care about the date value and just want to know that it IS a Date object, just use EasyMock's predefined matcher:

EasyMock.expect(objectMock.isPollingTimeOut(EasyMock.eq(600000L), EasyMock.isA(Date.class), EasyMock.eq(someMock))).andReturn(false);

Remember, once you use a matcher, you've to use matchers for all arguments in the method you're testing like what I did.

If you can figure out exactly why it's failing, you can write your own matcher to be more flexible in matching the date. See the section on matchers http://easymock.org/EasyMock2_2_Documentation.html

It could be that the millisecond part of the dates are different. You probably need to zero that using Calendar.set() before you create the date object:

Calendar myCalendar = Calendar.getInstance();
myCalendar.set(Calendar.MILLISECOND, 0);
Date testDate = myCalendar.getTime();

But that is a guess :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top