热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何测试使用DateTime获取当前时间的函数?-HowcanItestafunctionthatusesDateTimetogetthecurrenttime?

MostoftheanswersIhaveseenonStackOverflowarewithoutusingtheDateTimeobject,andareinst

Most of the answers I have seen on StackOverflow are without using the DateTime object, and are instead using the date() function. This makes them very dirty solutions (overriding date(), mocking a protected function of the subject under test, etc).

我在StackOverflow上看到的大多数答案都没有使用DateTime对象,而是使用了date()函数。这使得它们成为非常脏的解决方案(覆盖date(),模拟受测试对象的受保护功能等)。

Is there a way to mock DateTime, effectively mocking the current date/time?

有没有办法模拟DateTime,有效地模拟当前日期/时间?

As an example, here is the code I'd like to test:

举个例子,这是我要测试的代码:

public function __construct(UserInterface $user, EntityManager $manager)
{
    $this->user = $user;
    $this->manager = $manager;
}

public function create(Tunnel $tunnel, $chain, $response)
{
    $history = new CommandHistory();

    $history->setTunnel($tunnel)
        ->setCommand($chain)
        ->setResponse($response)
        ->setUser($this->user)
    ;

    $this->manager->persist($history);
    $this->manager->flush();
}

Here is where I set the date and time in my CommandHistory class:

这是我在CommandHistory类中设置日期和时间的地方:

class CommandHistory
{
    // Property definitions...

    public function __construct()
    {
        $this->time = new \DateTime();
    }
}

And here is my unit test:

这是我的单元测试:

public function testCreate()
{
    $user = new User();
    $manager = $this->mockManagerWithUser($user);

    $tunnel = $this->tunnel;
    $chain = 'Commands`Chain';
    $respOnse= 'This is the response!';

    $creator = new CommandHistoryCreator($user, $manager);
    $creator->create($tunnel, $chain, $response);
}

protected function mockManagerWithUser(UserInterface $user)
{
    $manager = \Mockery::mock('Doctrine\ORM\EntityManager');

    $manager->shouldReceive('persist')->once()->with(\Mockery::on(function(CommandHistory $argument) use ($user) {
        return
            $argument->getCommand() === 'Commands`Chain'
            && $argument->getResponse() === 'This is the response!'
            && $argument->getTunnel() === $this->tunnel
            && $argument->getUser() === $user
        ;
    }));
    $manager->shouldReceive('flush')->once()->withNoArgs();

    return $manager;
}

As you can see, I've created a rather long-winded closure only to exclude the comparison of the field that contains the current time, and I feel like this is hurting the readability of my test.

正如你所看到的,我创建了一个相当冗长的闭包只是为了排除包含当前时间的字段的比较,我觉得这会损害我的测试的可读性。

Also, to preserve ease of use for people who are using this class, I don't want to have to make them pass in the current time to the create() function. I believe adding strange behavior to my classes only to make them testable means I'm doing something wrong.

此外,为了保持使用此类的人的易用性,我不想让它们在当前时间传递给create()函数。我认为在我的类中添加奇怪的行为只是为了使它们可测试意味着我做错了。

1 个解决方案

#1


So the standard approach to solving this relies on accepting that in your current implementation you have a static, implicit, undeclared dependency on an object which provides the current time (wrapped in a the new instance of the DateTime object). If you did this with your own code (rather than a class from the framework/language) you would not be able to test easily either.

因此,解决此问题的标准方法依赖于接受在当前实现中对对象提供静态,隐式,未声明的依赖关系,该对象提供当前时间(包含在DateTime对象的新实例中)。如果您使用自己的代码(而不是框架/语言中的类)执行此操作,您将无法轻松地进行测试。

The solution is to stop using the implicit undeclared dependency and declare your implicit dependency explictly. I would do this by creating a DateTimeProvider (or DateTimeFactory) interface which has a method GetCurrentDateTime. Pass this into your constructor for your CommandHistoryCreator and pass it into the CommandHistory constructor. The CommandHistory will then ask the provider to get the current date time object rather than creating a new one itself, and can carry on as it is.

解决方案是停止使用隐式未声明的依赖关系并明确声明隐式依赖关系。我会通过创建一个具有GetCurrentDateTime方法的DateTimeProvider(或DateTimeFactory)接口来完成此操作。将其传递给CommandHistoryCreator的构造函数,并将其传递给CommandHistory构造函数。然后,CommandHistory将要求提供者获取当前日期时间对象,而不是自己创建一个新对象,并且可以继续保持原样。

This will allow you to provider a mock DateTime in your tests and check that the CommandHistory is persisted with the correct DateTime

这将允许您在测试中提供模拟DateTime,并检查CommandHistory是否使用正确的DateTime持久化


推荐阅读
  • 本文深入探讨了 Delphi 中类对象成员的核心概念,包括 System 单元的基础知识、TObject 类的定义及其方法、TClass 的作用以及对象的消息处理机制。文章不仅解释了这些概念的基本原理,还提供了丰富的补充和专业解答,帮助读者全面理解 Delphi 的面向对象编程。 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 如何解决《PHPUnit和Abstract类:如何测试接受参数和其他具体方法的具体构造函数》经验,应该怎么弄,您有好建议吗? ... [详细]
  • 如何解决《是否可以在不扩展PHPUnit_Framework_TestCase的情况下使用PHPUnit断言?》经验,为你挑选了1个好方法。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 本文探讨了如何在Classic ASP中实现与PHP的hash_hmac('SHA256', $message, pack('H*', $secret))函数等效的哈希生成方法。通过分析不同实现方式及其产生的差异,提供了一种使用Microsoft .NET Framework的解决方案。 ... [详细]
  • 优化SQL Server批量数据插入存储过程的实现
    本文介绍了一种改进的SQL Server存储过程,用于生成批量插入语句。该方法不仅提高了性能,还支持单行和多行模式,适用于SQL Server 2005及以上版本。 ... [详细]
  • 本文探讨了如何利用HTML5和JavaScript在浏览器中进行本地文件的读取和写入操作,并介绍了获取本地文件路径的方法。HTML5提供了一系列API,使得这些操作变得更加简便和安全。 ... [详细]
  • ListView简单使用
    先上效果:主要实现了Listview的绑定和点击事件。项目资源结构如下:先创建一个动物类,用来装载数据:Animal类如下:packagecom.example.simplelis ... [详细]
  • 本文将详细探讨 Java 中提供的不可变集合(如 `Collections.unmodifiableXXX`)和同步集合(如 `Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。 ... [详细]
  • 闭包函数,即匿名函数,在PHP中通过Closure类表示。本文将探讨如何访问闭包内的static、this及parameter等关键属性。 ... [详细]
  • phpunit自定义的示例分析
    这篇文章主要介绍phpunit自定义的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!下载:wget  https:phar ... [详细]
author-avatar
dengyuanc_928
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有