我有一个PHP类,当我为其创建新实例时,会在MySQL数据库中使用CURRENT_TIMESTAMPS创建一行。然后使用此时间戳对这些记录进行排序(并主要获取最后一个)。
在这种精确的情况下,时间戳是Eloquent(Laravel)模型的自动生成的created_at
列。如果可能的话,我想要一个不是Laravel特定的解决方案,因为我可能在其他项目中遇到同样的问题。
我已经在另一台PC上为该课程编写了测试,并且一切正常,结果总是正确的。
现在,我将此项目复制到另一台具有SSD且比另一台功能强大(但不多)的PC上。现在,我所有的测试都失败了,因为所有记录最终都具有完全相同的时间戳。
在生产中,如果两个记录具有相同的时间戳记(这是不太可能的)就不会成为问题,但这不是我尝试在测试中复制的情况。
为了快速解决该问题而无需深入研究代码,我在实例化新对象之前添加了一些sleep(1)函数。
但是现在我的问题是,解决该问题的最佳方法是什么?
我想到了以下几种可能性,但我不确定哪一种是最好的:
在测试中对日期进行硬编码:没有失败的风险,但是我的对象当前无法提供手动定义日期的方法。我需要为此添加方法,并且它们将不会用于其他任何事情。
在执行下一个操作之前,清空数据库。问题在于,对于某些测试,我需要一个接一个地插入两个对象,因此无法解决所有问题
让代码等待。但这对我来说听起来很愚蠢,因为我失去了拥有强大机器的所有好处。当然,运行测试需要更多时间
操纵系统或数据库的当前时间。如果尝试这样做,我不知道会发生什么可怕的事情!也许可以隔离执行此操作的过程而不会影响PC上的其他任何内容?
那么您推荐哪种方法呢?有更好的吗?
更多系统信息:我所有的开发机都在运行带有PHP 5.5和MySQL 5.5的Ubuntu 14.04。我当前的项目使用Laravel 4框架和phpunit进行测试
附加信息
我想在下面的评论中添加我所说的内容。
理想情况下,我的测试应该使用相隔多个小时的日期来进行断言,但是目前,我依靠的事实是两个记录至少相差一秒钟,而其他PC配置则不再如此。
并且,在生产中,附加信息通常会在插入新记录或查询数据库之前(例如90%的时间)删除较旧的记录,因此即使快速创建了两个记录,也有可能删除一个记录。在对数据库进行逻辑处理之前。但是对于我的测试,我需要在数据库中至少有两条记录,间隔一定的时间,这并不重要,但大于零。
最佳答案
我发现了一个仅适用于Eloquent的好的解决方案。
这与用于数据库种子的相同。
我们可以在实例化测试中的对象之前添加Eloquent::unguard()
:
Eloquent::unguard();
Model::create(array('created_at' => '2014-12-17'));
因此,我们可以手动设置模型的
created_at
字段,而不必将其暴露给使用该类的“每个人”。