gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 17:08:48 28 4
gpt4 key购买 nike

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

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

例如,这是我要测试的代码:

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

这是我在 CommandHistory 中设置日期和时间的地方类(class):
class CommandHistory
{
// Property definitions...

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

这是我的单元测试:
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;
}

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

另外,为了方便使用这个类的人,我不想让他们在当前时间传递给 create()功能。我相信在我的类(class)中添加奇怪的行为只是为了让它们可测试意味着我做错了什么。

最佳答案

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

解决方案是停止使用隐式未声明的依赖并显式声明您的隐式依赖。我会通过创建 DateTimeProvider 来做到这一点(或 DateTimeFactory )具有方法 GetCurrentDateTime 的接口(interface).将此传递给您的构造函数,用于您的 CommandHistoryCreator并将其传递给 CommandHistory构造函数。 CommandHistory然后将要求提供者获取当前日期时间对象,而不是自己创建一个新对象,并且可以继续进行。

这将允许您提供一个模拟 DateTime在您的测试中并检查 CommandHistory坚持正确的DateTime

关于unit-testing - 如何测试使用 DateTime 获取当前时间的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30136981/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com