Mockito 单元测试 - 时间戳不同



在Mockito测试中遇到一些问题。

我目前收到此错误:

Argument(s) are different! Wanted:
repository.save(
uk.co.withersoft.docservice.repositories.hibernate.MetaDataEntity@3e437e6c
);
-> at uk.co.withersoft.docservice.datastore.impl.MetaDataStoreImplTest.storeClaimMetadata(MetaDataStoreImplTest.java:55)
Actual invocation has different arguments:
repository.save(
uk.co.withersoft.docservice.repositories.hibernate.MetaDataEntity@3e361ee2
);

我很确定这是因为MetaDataEntity内的时间不同

这就是我应该得到的

id = null
metaData = "{"caseReference":"CN00000001","claimReference":"LN00000001","rpsDocumentType":"REJ","documentTitle":"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter"}"
batchId = 0
state = "Saved MetaData to DB"
lastUpdatedDate = {Timestamp@1517} "2018-07-25 18:39:21.993"
createdDate = {Timestamp@1518} "2018-07-25 18:39:21.993"

这实际上是我得到的。

id = null
metaData = "{"caseReference":"CN00000001","claimReference":"LN00000001","rpsDocumentType":"REJ","documentTitle":"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter"}"
batchId = 0
state = "Saved MetaData to DB"
lastUpdatedDate = {Timestamp@1530} "2018-07-25 18:39:49.274"
createdDate = {Timestamp@1531} "2018-07-25 18:39:52.716"

这是我的测试用例:

@Test
public void storeClaimMetadata () throws JsonProcessingException {
ClaimMetaData metaData = constructMetaData();
MetaDataEntity mockResponseMetaDataEntity = new MetaDataEntity();
mockResponseMetaDataEntity.setId(1);
when(repository.save(any(MetaDataEntity.class))).thenReturn(mockResponseMetaDataEntity);
Integer result = testSubject.storeClaimMetadata(metaData);
assertEquals(Integer.valueOf(1), result);
final ObjectMapper mapper = new ObjectMapper();
String jsonMetaData = mapper.writeValueAsString(metaData);
MetaDataEntity expectedMetaDataEntity = new MetaDataEntity(null,
jsonMetaData,
0,
"Saved MetaData to DB",
new Timestamp(System.currentTimeMillis()),
new Timestamp(System.currentTimeMillis()));
Mockito.verify(repository, times(1)).save(expectedMetaDataEntity);
}
//Creates a ClaimRequest
private ClaimMetaData constructMetaData() {
final ClaimMetaData metaData  = new ClaimMetaData("CN00000001",
"LN00000001",
"REJ",
"Claims LN00000001 (Claimant: Mr LOCAL HOST) REJ-Rejection letter");
return metaData;
}

任何帮助将不胜感激。这让我发疯了!!

这正是人们使用依赖注入的原因,因此他们可以指定返回可预测结果的测试协作者。将硬编码的new Timestamp(System.currentTimeMillis)内容替换为对Timestamp.from(Instant.now(clock))的调用。

java.time.Clock是一个可用于获取时间戳值的接口。真正的实现可以注入到正在测试的代码中,使用返回系统时钟的工厂方法之一,如下所示(使用 Spring Java 配置):

@Bean
public Clock clock() {
return Clock.systemDefaultZone();
}

对于测试代码,您可以有一个实现,在其中指定希望时钟返回的时间:

@Before 
public void setUp() {
clock = Clock.fixed(date.toInstant(), ZoneId.of("America/NewYork"));
systemUnderTest.setClock(clock);
}

这是"按设计工作"。

您正在调用计算时间戳的服务。就像,现在。

然后,您有一个测试用例,该用例正在进行一些设置,并且还获取时间戳。现在。

你猜怎么着:虽然上面这两个"现在"彼此接近,但它们之间还是有一点延迟。

您正在检查相等性,只有在时间戳相同才能工作!但它们不是,因为它们是一个接一个地创建的,中间有非常明显的延迟!

意思是:你需要看看如何控制在应用程序中创建哪些时间戳,比如说"时间戳应该是t1和t2"。这样您的测试就可以检查"我找到了 t1 和 t2"。

或者,您只需更改验证步骤:而不是尝试拥有"相等"的对象(由于时间戳不同而不能相等!),您可以比较那些应该相等的部分,对于时间戳,您可以检查它们是否"足够接近"。

在代码中,可以使用new Timestamp(System.currentTimeMillis()),而不是使用new Timestamp(DateTimeUtils.currentTimeMillis()).这里DateTimeUtils来自jodatime。

在测试用例中,可以使用下面。

private SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss:SSS");
@Before
public void before() throws Exception {
// define a fixed date-time
Date fixedDateTime = DATE_FORMATTER.parse("01/07/2016 16:45:00:000");
DateTimeUtils.setCurrentMillisFixed(fixedDateTime.getTime());
}
@After
public void after() throws Exception {
// Make sure to cleanup afterwards
DateTimeUtils.setCurrentMillisSystem();
}````

最新更新