Closed elvetemedve closed 2 months ago
As DateTime is a value object, I would suggest using an actual one instead of mocking it (and otherwise, you have to configure the mock to actually behave like the PHP class, which is your responsibility if you create a mock for it, which is the main reason for the common saying "don't mock what you don't own")
This is not something that can be fixed in prophecy as prophecy cannot autoconfigure a mock to behave like the actual class (as it does not know how it is supposed to behave).
Summary
When you want to use
\DateTime
object in PHPSpec tests as dummy object, then the test fails with the following error message:The Problem
Let's suppose we have two classes
Subject
andCollaborator
and we are writing spec for the former. Source code looks like this:composer.json
Finally execute the tests:
vendor/bin/phpspec run
Actual Result
Expected Result
Explanation
Prophecy uses the
DateTimeComparator
class fromsebastian/comparator
package from theExactValueToken
class in order to compare the actual date argument with the argument of the promise object. That worked fine before 2.1.1 or earlier versions. But in 2.1.2 methods of the\DateTime
class are chained like$expected->setTimezone()->sub()
. Since$expected
is not a real\DateTime
object, but actually a dummy test double, all of the methods will returnnull
by definition. Therefore$expected->setTimezone()
becomesnull
, that's whysub()
cannot be called on that.Since our compared object is not a real
\DateTime
, it should not be compared by theDateTimeComparator
. The condition to support an object is to check the inheritance chain, it will be accepted for comparison which is fine when the real\DateTime
class is extended.