简体   繁体   English

Mockito 单元测试 - 时间戳不同

[英]Mockito Unit tests - Timestamps are different

Having some issues with a Mockito test. Mockito 测试有一些问题。

I currently get this error:我目前收到此错误:

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

I'm pretty sure its because the times within MetaDataEntity are different我很确定这是因为MetaDataEntity中的时间不同

//This is what I should be getting //这是我应该得到的

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"

// This is actually what I get. // 这实际上是我得到的。

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"

Here is my test case:这是我的测试用例:

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

Any help would be much appreciated.任何帮助将非常感激。 This has been driving me crazy!!这让我发疯了!!

This is exactly why people use dependency injection, so they can specify test collaborators that give back predictable results.这正是人们使用依赖注入的原因,因此他们可以指定返回可预测结果的测试合作者。 Replace the hardcoded new Timestamp(System.currentTimeMillis) stuff with calls to Timestamp.from(Instant.now(clock)) .用对Timestamp.from(Instant.now(clock))调用替换硬编码的new Timestamp(System.currentTimeMillis)内容。

java.time.Clock is an interface that you can use to get your timestamp values. java.time.Clock是一个可用于获取时间戳值的接口。 The real implementation can be injected into the code being tested, using one of the factory methods that returns a system clock, like this (using Spring Java configuration):可以使用返回系统时钟的工厂方法之一将真正的实现注入到正在测试的代码中,如下所示(使用 Spring Java 配置):

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

and for the test code you can have an implementation where you specify the time you want the clock to return:对于测试代码,您可以有一个实现,您可以在其中指定希望时钟返回的时间:

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

This is "works as designed".这是“按设计工作”。

You are invoking a service that computes timestamps.您正在调用计算时间戳的服务。 Like, now.像现在。

Then you have a test case that has some setup going on, and fetches time stamps, too.然后你有一个测试用例,它有一些设置正在进行,也获取时间戳。 Now.现在。

Guess what: albeit these two "nows above are close to each other, there is still a bit of delay between them.猜猜看:虽然上面的这两个“现在”彼此接近,但它们之间仍然存在一些延迟。

You are checking for equality, can only work when the time stamps are identical !要检查是否相等,当时间标志完全相同只能工作! But they aren't, because they are created one after the other, with very well noticeable delays in between!但它们不是,因为它们一个接一个地创建,中间有非常明显的延迟!

Meaning: you need to look how you could control which timestamps are created within your application, like saying "the timestamps should be t1 and t2".含义:您需要查看如何控制在应用程序中创建的时间戳,例如“时间戳应该是 t1 和 t2”。 So that your test can then check "I found t1 and t2".这样您的测试就可以检查“我找到了 t1 和 t2”。

Alternatively, you simply change your verification step: instead of trying to have "equal" objects (that can't be equal because different time stamps!), you could compare those parts that should be equal, and for the time stamps, you could check that they are "close enough".或者,您只需更改验证步骤:您可以比较那些应该相等的部分,而不是尝试使用“相等”的对象(因为时间戳不同,所以不能相等!),对于时间戳,您可以检查它们是否“足够接近”。

In Code , instead of using new Timestamp(System.currentTimeMillis()) , you can use new Timestamp(DateTimeUtils.currentTimeMillis()) .在 Code 中,您可以使用new Timestamp(DateTimeUtils.currentTimeMillis())而不是使用new Timestamp(System.currentTimeMillis()) new Timestamp(DateTimeUtils.currentTimeMillis()) Here DateTimeUtils is from jodatime.这里 DateTimeUtils 来自 jodatime。

In test cases, can use below.在测试用例中,可以在下面使用。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM