微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有办法每次使用 EasyMock return anyTimes() 返回一个新对象?

如何解决有没有办法每次使用 EasyMock return anyTimes() 返回一个新对象?

我正在为一个严重依赖日历的类进行单元测试。我正在尝试模拟所有调用,以便我基本上可以将我自己指定的系统时间插入到类中以进行一些日期时间逻辑测试。

这是我的第一次尝试:

Calendar fixedSystemCal = Calendar.getInstance();
fixedSystemCal.set(2021,Calendar.FEBRUARY,22,18,0);

PowerMock.mockStatic(Calendar.class);
EasyMock.expect(Calendar.getInstance()).andReturn(fixedSystemCal).anyTimes();
PowerMock.replay();

不幸的是,经过一番摸索,我发现这行不通,因为日历对象在类中发生了变异。由于这个模拟每次返回相同的日历,这是一个问题。例如:

Calendar firstCall = Calendar.getInstance(); //Feb 22
firstCall.add(Calendar.DATE,5); //Feb 27

Calendar secondCall = Calendar.getInstance() // This is also Feb 27 Now

有什么办法可以每次都取回不同的日历对象(对于任意数量调用)?到目前为止,我找到的唯一解决方案就是像这样重复多次:

Calendar fixedSystemCal = Calendar.getInstance();
fixedSystemCal.set(2021,0);

PowerMock.mockStatic(Calendar.class);
EasyMock.expect(Calendar.getInstance()).andReturn((Calendar) fixedSystemCal.clone()).andReturn((Calendar) fixedSystemCal.clone()).andReturn((Calendar) fixedSystemCal.clone());
PowerMock.replay();

我将在下一步中用 Java 时间替换这段代码,但我需要一个功能正常的单元测试才能进行更改。

解决方法

您应该能够使用 andAnswer 而不是 andReturn 来提供可用于返回新实例的 lambda/IAnswer 实现。类似的东西:

EasyMock.expect(Calendar.getInstance())
   .andAnswer(() -> (Calendar)fixedSystemCal.clone());
,

您需要使用 andAnswer 而不是 andReturn。尽管它们的名字看起来很相似,但它们在模拟和测试过程中都有不同的用途。如果您需要使用静态值(始终相同的实例),请使用 andReturn。如果您需要使用动态值或派生值,请使用 andAnswer。

代码示例

Calendar fixedSystemCal = Calendar.getInstance();
fixedSystemCal.set(2021,Calendar.FEBRUARY,22,18,0);

PowerMock.mockStatic(Calendar.class);
EasyMock.expect(Calendar.getInstance()).andReturn((Calendar) fixedSystemCal.clone()).andReturn((Calendar) fixedSystemCal.clone()).andReturn((Calendar) fixedSystemCal.clone());
PowerMock.replay();

EasyMock.expect(Calendar.getInstance()).andAnswer(() -> (Calendar) fixedSystemCal.clone());

并返回

andReturn 设置调用方法时要返回的值。此值将始终是您定义的相同实例。在您的情况下,它将返回 fixedSystemCal.clone() 的值,该值将始终与您克隆一次的日历实例相同。可以将其视为将克隆保存在变量中,并在调用方法时始终返回相同的变量。

只有当您在模拟方法调用时知道返回值时才应该使用 andReturn。当您调用模拟方法时,将返回此预定义值。

如果您希望以常规代码表示。模拟方法 getDate 看起来像这样,您始终返回相同的日历实例:

private Calendar calendar = Calendar.getInstance();

public Calendar getCalendar() {
    return calendar;
}

andAnwser

andAnwser 将在返回值之前执行一个方法。当您需要在调用模拟方法时执行附加操作时,可以使用此方法,例如当你需要克隆一个对象或者你想根据传递的参数执行一些逻辑时。

如果您希望以常规代码表示。模拟一个方法 getDate 看起来像这样,你总是返回一个新的 Calendar 实例:

public Calendar getCalendar() {
    return Calendar.getInstance();
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。