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

How to compare new Date in unit test?

我有service方法:

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

如果Entity equals()没有比较Date那么一切都好但是如果比较Date那么 测试抛出 Argument(s) are different!

您有 2 个选择:

方案一:使用时钟class控制时间

而不是使用new Date()

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

Guide to the Java Clock Class

方案一:放宽匹配要求

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

您的 equals 方法的定义可能有问题。 您应该定义在什么情况下两个不同的实体被认为是相等的:

只有当两个实体的日期值在相同的范围内时才相等
毫秒还是我们只关心秒、分钟或天?

类似于处理浮点值,这个可接受的差异可以类似于Calculating the difference between two Java date instances

计算

而不是依赖于您的解决方案中使用的 equals 方法:

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

您可以尝试捕获参数并在下一步中声明它,如 Verify object attribute value with mockito

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

据我了解,无法更改服务和实体。那么在这种情况下,最好在 Mockito.

中使用 ArgumentMatcher<>

第 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 这将是比较对象。 mathces 可以是 ovveride 随心所欲。我觉得一秒的差距就够了

第 2 步:

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

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

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