代码之家  ›  专栏  ›  技术社区  ›  Chrisissorry

PHPUnit表单测试在DateTime失败

  •  0
  • Chrisissorry  · 技术社区  · 8 年前

    4) Tests\AppBundle\Form\AssetStatusTypeTest::testValidForm with data set #0 (array('active'))
    Failed asserting that two objects are equal.
    --- Expected
    +++ Actual
    @@ @@
         'status' => 'active'
        'type' => null
        'amount' => null
    -    'createdAt' => 2018-09-20T20:34:47.047520+0200
    +    'createdAt' => 2018-09-20T20:34:47.047870+0200
         'updatedAt' => null
         'contract' => null
         'admin' => null
    

    public function testValidForm($data)
    {
        $form = $this->factory->create(AssetStatusType::class);
        $object = Entity::fromArray(new Asset(), $data);
        $form->submit($data);
        $this->assertTrue($form->isSynchronized());
        $this->assertEquals($object, $form->getData());
        $view = $form->createView();
        $children = $view->children;
        foreach (array_keys($data) as $key) {
            $this->assertArrayHasKey($key, $children);
        }
    }
    

    多少是 copied from the docs .

    createdAt 字段设置如下:

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

    我的主要观点是:这个测试通过了我们的詹金斯。它不在几个开发人员机器上本地运行。我的第一个冲动是检查ini时区设置。

    object 已创建,实际值为提交表单时的值。所以两个物体不能有相同的 precision 可能是超低。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Alister Bulman    8 年前

    这两台机器运行的是不同版本的PHP。PHP7.1(及更高版本)在创建DateTime对象时包含微秒,但在php5.x和7.0上运行的代码不会。

    有两种方法可以解决这个问题:

    • 不要比较精确的日期时间,而是将它们转换为秒 $datetimeObj->format('U'); . 当一个测试在1.99998创建,下一个创建datetime的调用在2.0001时,仍然会偶尔出现测试失败,因此当转换为秒时,测试仍然失败。
    • Clock Mocking time() 函数被重写( sleep() 也是)。您必须创建新的DateTime对象,以确保它们实际使用新版本的time()函数,但时钟实际上会停止,sleep()会变成更像 $time += $seconds; sleep(3600); 有效时间为零。

    symfony/phpunit桥ClockMock.php 如果您不想在PHPunit配置中包含它作为侦听器,则可以将其用作库。

    推荐文章