Easymock使用日期期望

时间:2010-01-28 14:21:34

标签: java date easymock

我正在使用easymock模拟一个方法,该方法在其正文中有一个日期,如下所示:

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

我的测试看起来像这样:

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

但是当我运行测试时,有时会出现这样的错误:

  

意外的方法调用testsMethod(Thu Jan 28 09:45:13 GMT-03:00 2010):       testsMethod(Thu Jan 28 09:45:13 GMT-03:00 2010):预期:1,实际:0

我认为这是因为有时日期略有不同。我没有成功地尝试了一些灵活的期望。有办法解决这个问题吗?

6 个答案:

答案 0 :(得分:4)

停止使用新的日期(),改为使用具有恒定时间的日历。

//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);
    ...
}

答案 1 :(得分:4)

我们经常面临类似的问题,这些是我看到的替代方案:

  1. 提供日期作为方法的参数 (+)快速变化 ( - )有点脏 - 当你只想使用“现在”时,它也会污染你的界面
  2. 从协作者“QueryCurrentDateProvider”中提取日期 (+)还很快 (+)也可以嘲笑 - >你确定你使用相同的日期 ( - )为您需要执行类似操作的每项服务创建的不必要的协作者
  3. 编写你自己的EasyMock参数匹配器,在那里你抽象出你真正想要做的事情 - 当你只对当天感兴趣时,而不是你可以使用像commons DateUtils.isSameDay这样的东西来运行 (+)最干净的解决方案 (+)您的生产代码没有变化 ( - )你必须编写自己的匹配器(虽然我不明白为什么EasyMock还没有它)
  4. 将“new Date()”移动到私有方法,然后使用类似PowerMock的方法模拟此方法 (+)快 (+)对生产代码的小改动 ( - )将power mock作为依赖引入
  5. 将参数从Date更改为String,并在调用方法之前使用通用模式将日期转换为字符串 (+)快 (+)没有其他代码,测试网站上需要的库 ( - )您必须在调用方法之前格式化日期并在被调用方法中解析日期
  6. 所以这真的取决于你个人的喜好。当你正在使用当前的时间戳时,我会推荐参数匹配器 - 因为这项投资会很快得到回报。

答案 2 :(得分:3)

我刚刚找到了这个帖子,它帮助我解决了一个问题,我被困在了一个小时。

以为我会分享我的2美分:

如果您不关心日期值,只想知道它是一个Date对象,只需使用EasyMock的预定义匹配器:

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

请记住,一旦使用匹配器,就必须使用匹配器来测试您正在测试的方法中的所有参数。

答案 3 :(得分:2)

如果你能弄清楚它失败的确切原因,你可以编写自己的匹配器,以便更灵活地匹配日期。请参阅匹配器http://easymock.org/EasyMock2_2_Documentation.html

部分

答案 4 :(得分:2)

可能是日期的毫秒部分不同。在创建日期对象之前,您可能需要使用Calendar.set()将其归零:

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

但这是猜测:)

答案 5 :(得分:0)

使用自定义EasyMock Matcher进行宽松日期比较。这是一个示例,将检查日期是否彼此之间在一秒之内。

public class MyEasyMockMatchers {

    public static Date withinSecondOf(Date value){
        EasyMock.reportMatcher(new IArgumentMatcher() {
            @Override
            public boolean matches(Object argument) {
                return argument instanceof Date
                        && Math.abs(((Date) argument).getTime() - value.getTime()) < Timer.ONE_SECOND;
            }

            @Override
            public void appendTo(StringBuffer buffer) {
                buffer.append(value.toString());
            }
        });
        return null;
    }
}

然后在您的测试中使用:

import static my.package.MyEasyMockMatchers.*;
...
expect(testedClass.testedMethod(withinSecondOf(new Date())))
        .andReturn(false);

请注意,当您使用一个匹配器时,必须为整个期望使用匹配器。例如:

expect(testedClass.testedMethod(42, "hello", new Date()))
        .andReturn(false);
// becomes
expect(testedClass.testedMethod(eq(42), eq("hello"), withinSecondOf(new Date())))
        .andReturn(false);

请参阅:https://easymock.org/user-guide.html#verification-expectations