Reputation: 1514
I have several unit tests failing on my local machine because DateTime values differ:
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
The test:
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);
}
}
Which is more or less copied from the docs.
Now, the createdAt
field is set like this:
public function __construct()
{
if (empty($this->createdAt)) {
$this->createdAt = new \DateTime();
}
}
My main point is: This test is passing on our Jenkins. It does not locally on several developer machines. My first impulse was to check ini timezone settings.
I wonder how this is even possible. If I get it right, expected is when object
was created and actual is when the form is submitted. So both objects can never have the same createdAt
timestamp. Unless precision
is probably super low.
Upvotes: 1
Views: 1626
Reputation: 35139
The two machines are running different versions of PHP. PHP7.1 (and above) includes microseconds when it creates a DateTime object, but code running on PHP 5.x and 7.0, won't.
There are two ways to work with this:
$datetimeObj->format('U');
. You'll still get occasional test failures when one test is created at say 1.99998 and the next call to create a datetime is at 2.0001, and so the test still fails when converted to seconds.time()
function is overridden (sleep()
too). You have to create new DateTime object to make sure they actually use the new version of the time() function, but the clock would effectively stop - and sleep()'s just turn into something more like $time += $seconds;
- which also means that a sleep(3600);
takes effective zero time.The symfony/phpunit-bridge ClockMock.php can be used just as a library if you don't want to include it as a listener in your PHPunit configuration.
Upvotes: 2