如何在单元测试中比较新日期?

5

我有一个带有方法的服务

Entity entity = new Entity(new Date(), 1, 2L);
return entityRepository.save(entity);

我的测试:

@Test
public void testSaveEntity() {
    Entity entity = new Entity(new Date(), 1, 2L);
    entityService.saveEntity(1, 2L);
    verify(entityRepository, times(1)).save(entity);
} 

如果Entityequals()方法不比较Date,一切都好,但是如果比较Date,那么测试会抛出Argument(s) are different!异常。

2
我可以问一下,你为什么要使用 Date - MC Emperor
1
我强烈建议您不要使用Date。这个类设计很差,而且已经过时了。相反,应该使用适当的类来自于java.time,现代Java日期和时间API - Ole V.V.
1
尽管名称为“Date”,但它并不代表日期,而是表示具有毫秒精度的时间点。因此,如果您在几毫秒之间调用new Date(),则很可能会得到两个不相等的对象。这很令人困惑。使用java.time,并像Lesiak所说的那样使用java.time.Clock - Ole V.V.
1
Java有两个Date类,分别是java.util.Datejava.sql.Date。这两个类都存在严重缺陷,应该避免使用。多年前,它们被现代的java.time类所取代。具体而言,分别被InstantLocalDate所替代。 - Basil Bourque
4个回答

3
据我的理解,无法更改服务和实体。在这种情况下,最好使用ArgumentMatcher<>Mockito中。 步骤1:
@AllArgsConstructor
public class EntityMatcher implements ArgumentMatcher<Entity> {

    private Entity left;

    @Override
    public boolean matches(Entity right) {
        return (left.getEventDate().getTime() - right.getEventDate().getTime() <= 1000));
    }
}

在这里,您可以重写equals方法来比较对象,matches方法可以随意重写。我认为一秒钟的差异足够了。

步骤 2:

verify(entityRepository).save(argThat(new EntityMatcher(new Entity(new Date(), 1, 2L))));

其他情况: 在其他测试中,很可能会出现这样的情况,即需要在 when 时检查此 entity

when(entityRepository.save(any(Entity.class))).thenReturn(new Entity(new Date(), 1, 2L));

2

您有两个选择:

选项1:使用Clock类控制时间

不要使用new Date()

  • Clock实例注入到您的服务中
  • 使用其方法检索当前时间
  • 在测试代码中,使用Clock.fixed来控制当前时间

请参阅Java Clock Class指南

选项2:放宽匹配要求

使用Mockito ArgumentMatchers来放宽匹配要求-使用any(YourEntity.class)匹配任何YourEntity,或为您的实体编写自定义参数匹配器。


很遗憾,Clock我无法修改。 any(Date.class)似乎在when()结构中被使用。 - Uga Rimad
  1. 对不起,但我不明白。您的意思是您不能更改您的代码吗?
  2. 您也可以在verify中使用参数匹配器。
- Lesiak

2

您可能遇到了equals方法的定义问题。您应该明确在哪种情况下认为两个不同的实体是相等的:

仅当它们的日期值在同一毫秒内时,这两个实体才被视为相等,还是我们只关心秒、分钟或天数?

类似处理浮点数值,可以通过类似计算两个Java日期实例之间的差异来计算可接受的差异。


0

不要再依赖你解决方案中使用的equals方法:

verify(entityRepository, times(1)).save(entity);

你可以尝试在下一步中捕获参数并像使用Mockito验证对象属性值所描述的那样进行断言。

ArgumentCaptor<Entity> argument = ArgumentCaptor.forClass(Entity.class);
verify(entityRepository, times(1)).save((argument.capture());
assertEquals(1, argument.getValue().getWhatever());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接