ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java – 我可以使用mockito来匹配具有自动更新时间戳的对象吗?

2019-07-23 10:12:50  阅读:296  来源: 互联网

标签:java unit-testing mocking time mockito


在进行模拟调用之前自动更新时间戳的最佳方法是什么?

这是我试图测试的一些虚拟代码:

public class ThingWithATimestamp {
    public Long timestamp;
    public String name;

    public ThingWithATimestamp(String name) {
        this.name = name;
    }
}

public class TheClassThatDoesStuff {
    private ThingConnector connector;

    public TheClassThatDoesStuff(ThingConnector connector) {
        this.connector = connector;
    }

    public void updateTheThing(MyThingWithATimestamp thing) {
        thing.timestamp = currentTimestamp();
        connector.update(thing);            
    }
}

这是我想要测试的:

public class TheClassThatDoesStuffTests {
    @Test
    public void canUpdateTheThing() {
        ThingConnector connector = mock(ThingConnector.class);
        TheClassThatDoesStuff doer = new ThisClassThatDoesStuff(connector);

        doer.updateTheThing(new ThingWithATimestamp("the name"));

        verify(connector, times(1)).update(SomeMatcherThatICantFigureOut);
    }

我知道这段代码非常愚蠢,但我认为它准确地描绘了我想要验证的内容.我基本上需要一个匹配器来填写测试来验证时间戳是否在当前时间的X之内,所以我知道它已正确更新,并且使用适当的时间戳为对象调用了connector.update.

解决方法:

我发现处理时间关键代码最强大的方法是将所有时间关键函数包含在自己的类中.我通常称之为TimeHelper.所以这个类可能如下所示.

import java.util.Date;
public class TimeHelper{
    public long currentTimeMillis(){
        return System.currentTimeMillis();
    }
    public Date makeDate(){
        return new Date();
    }
}

它可能有更多相同类型的方法.现在,任何使用这些函数的类都应该有(至少)两个构造函数 – 您将在应用程序中使用的正常构造函数,以及一个包含TimeHelper作为参数的包私有构造函数.需要将此TimeHelper存储起来以备将来使用.

public class ClassThatDoesStuff {
    private ThingConnector connector;
    private TimeHelper timeHelper;

    public ClassThatDoesStuff(ThingConnector connector) {
        this(connector, new TimeHelper());
    }

    ClassThatDoesStuff(ThingConnector connector, TimeHelper timeHelper) {
        this.connector = connector;
        this.timeHelper = timeHelper;
    } 
}

现在,在您的类中,不要编写System.currentTimeMillis(),而是编写timeHelper.currentTimeMillis().当然,这将具有完全相同的效果;除了现在,你的班级神奇地变得更加可测试.

当你测试你的课程时,模拟一下TimeHelper.配置此模拟(使用Mockito的when和thenReturn,或者使用doReturn)返回您喜欢的任何时间值 – 无论您需要什么样的测试.如果您要在测试过程中多次调用currentTimeMillis(),您甚至可以在此处返回多个值.

现在使用第二个构造函数来创建您要测试的对象,并传入模拟.这使您可以完美控制测试中使用的时间值;并且您可以使您的断言或验证声明已经使用了正确的值.

public class ClassThatDoesStuffTest{
    @Mock private TimeHelper mockTime;
    @Mock private ThingConnector mockConnector;
    private ClassThatDoesStuff toTest;

    @Test
    public void doesSomething(){
        // Arrange
        initMocks(this);
        when(mockTime.currentTimeMillis()).thenReturn(1000L, 2000L, 5000L);
        toTest = new ClassThatDoesStuff(mockConnector, mockTime);

        // Act
        toTest.doSomething();

        // Assert
        // ... ???
    }
}        

如果这样做,您就知道您的测试将始终有效,并且永远不会依赖于操作系统的时间切片策略.您还可以验证时间戳的确切值,而不是断言它们落在某个近似间隔内.

标签:java,unit-testing,mocking,time,mockito
来源: https://codeday.me/bug/20190723/1512649.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有