如何在单元测试中比较新日期?
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));
我有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));