Như tôi đang sử dụng Symfony's WebTestCase để thực hiện chức năng kiểm tra bằng cách sử dụng thử nghiệm PHPUnit bó, nó nhanh chóng trở thành không thực tế để giả lập tất cả các tập quán của lớp DateTime.
tôi muốn thử nghiệm các ứng dụng như nó xử lý các yêu cầu theo thời gian, chẳng hạn như bánh thử nghiệm hoặc hết hạn bộ nhớ cache vv
Cách tốt nhất mà tôi đã tìm thấy để làm điều này là để thực hiện lớp DateTime của riêng tôi mà kéo dài lớp mặc định và cung cấp một số phương thức tĩnh để cho phép một khoảng thời gian mặc định được thêm vào/trừ đối với tất cả các đối tượng DateTime được tạo từ điểm đó trở đi.
Đây là một tính năng thực sự dễ thực hiện và không yêu cầu cài đặt thư viện tùy chỉnh.
caveat emptor: Hạn chế duy nhất để phương pháp này là khuôn khổ Symfony (hoặc bất kỳ khuôn khổ bạn đang sử dụng) sẽ không sử dụng thư viện của bạn, vì vậy hành vi nào nó dự kiến sẽ xử lý riêng của mình, chẳng hạn như nội cache/cookie sẽ hết hạn, sẽ không bị ảnh hưởng bởi những thay đổi này.
namespace My\AppBundle\Util;
/**
* Class DateTime
*
* Allows unit-testing of DateTime dependent functions
*/
class DateTime extends \DateTime
{
/** @var \DateInterval|null */
private static $defaultTimeOffset;
public function __construct($time = 'now', \DateTimeZone $timezone = null)
{
parent::__construct($time, $timezone);
if (self::$defaultTimeOffset && $this->isRelativeTime($time)) {
$this->modify(self::$defaultTimeOffset);
}
}
/**
* Determines whether to apply the default time offset
*
* @param string $time
* @return bool
*/
public function isRelativeTime($time)
{
if($time === 'now') {
//important, otherwise we get infinite recursion
return true;
}
$base = new \DateTime('2000-01-01T01:01:01+00:00');
$base->modify($time);
$test = new \DateTime('2001-01-01T01:01:01+00:00');
$test->modify($time);
return ($base->format('c') !== $test->format('c'));
}
/**
* Apply a time modification to all future calls to create a DateTime instance relative to the current time
* This method does not have any effect on existing DateTime objects already created.
*
* @param string $modify
*/
public static function setDefaultTimeOffset($modify)
{
self::$defaultTimeOffset = $modify ?: null;
}
/**
* @return int the unix timestamp, number of seconds since the Epoch (Jan 1st 1970, 00:00:00)
*/
public static function getUnixTime()
{
return (int)(new self)->format('U');
}
}
Sử dụng này rất đơn giản:
public class myTestClass() {
public function testMockingDateTimeObject()
{
echo "fixed: ". (new DateTime('18th June 2016'))->format('c') . "\n";
echo "before: ". (new DateTime('tomorrow'))->format('c') . "\n";
echo "before: ". (new DateTime())->format('c') . "\n";
DateTime::setDefaultTimeOffset('+25 hours');
echo "fixed: ". (new DateTime('18th June 2016'))->format('c') . "\n";
echo "after: ". (new DateTime('tomorrow'))->format('c') . "\n";
echo "after: ". (new DateTime())->format('c') . "\n";
// fixed: 2016-06-18T00:00:00+00:00 <-- stayed same
// before: 2016-09-20T00:00:00+00:00
// before: 2016-09-19T11:59:17+00:00
// fixed: 2016-06-18T00:00:00+00:00 <-- stayed same
// after: 2016-09-21T01:00:00+00:00 <-- added 25 hours
// after: 2016-09-20T12:59:17+00:00 <-- added 25 hours
}
}
Bạn đã không chấp nhận một câu trả lời nào. Bạn có thể vui lòng làm rõ những gì bạn đang tìm kiếm trong một câu trả lời và tại sao các câu trả lời nhất định không đáp ứng bạn. – Gordon
Đã có chính xác cùng một vấn đề, phần mở rộng timecop php từ câu trả lời của @shouze làm việc như một sự quyến rũ. –