【发布时间】:2018-04-11 05:54:37
【问题描述】:
从新的 phpunit 版本开始,\DateTime 对象与微秒精度进行比较。这并不总是一个好主意,因为如果我有这样的对象:
class QueueItem
{
public function __construct()
{
$this->setCreatedAt(new \DateTime('now', new \DateTimeZone('UTC')));
$this->setUpdatedAt(new \DateTime('now', new \DateTimeZone('UTC')));
}
}
我永远无法在我的测试中对整个对象使用assertEquals,因为日期时间属性总是会因微秒而不同。
仅比较对象时没什么大不了的(我可以分别比较每个字段)。但是问题来了:
$expectedQueue = [
new QueueItem(),
new QueueItem()
];
$this->repositoryWrite
->expects($this->once())
->method('save')
->with(...$expectedQueue);
with 比较整个参数数组,包括我无法预测的日期时间属性。
我唯一的解决方案是使用willReturnCallback 并分别比较每个参数:
$this->repositoryWrite
->expects($this->once())
->method('save')
->willReturnCallback(function(...$queue) use ($expectedQueue) {
/** @var QueueItem[] $queue */
foreach ($queue as $k => $queueItem) {
$this->assertEquals($expectedQueue->getSomeProp(), $queueItem[0]->getSomeProp());
}
});
看起来……嗯,很奇怪。这个还有其他解决方案吗?我可以更改 \DateTime 对象的比较器精度吗?
【问题讨论】:
-
你试过
DateTime::format()的方法吗? php.net/manual/en/datetime.format.php -
assertEquals()有一个可选的$delta参数正是为了这个目的。 -
@SebastianBergmann 是的,但是在 MockObject 的
with中没有这样的参数。这就是我要说的。 -
但是
with()使用约束对象。只需将其与equalTo()一起使用即可。 -
@SebastianBergmann,这将是一个非常复杂的约束。似乎 Hast 正在尝试同时测试多个事物。如果我明白了,
QueueItems 将在被测类中使用,并且模拟中的断言旨在确认对象在类中的某个位置正确构造。显然equalTo应该应用于QueueItem实例的所有属性,以便为DateTime使用正确的$delta。
标签: php unit-testing datetime phpunit