Como estoy usando Symfony's WebTestCase para realizar pruebas funcionales utilizando las pruebas PHPUnit paquete, rápidamente no fue práctico simular todos los usos de la clase DateTime.
quería probar la aplicación, ya que maneja las solicitudes a través del tiempo, tales como galletas o las pruebas de caducidad de la caché, etc.
La mejor manera que he encontrado para hacer esto es poner en práctica mi propia clase DateTime que se extiende la clase predeterminada, y proporciona algunos métodos estáticos para permitir que se agregue/resta un sesgo de tiempo predeterminado a todos los objetos DateTime que se crean a partir de ese punto en adelante.
Esta es una característica realmente fácil de implementar y no requiere la instalación de bibliotecas personalizadas.
caveat advertencia: está (o cualquier marco que está utilizando) no va a usar la biblioteca, por lo que cualquier comportamiento que se espera el marco Symfony El único inconveniente de este método para manejar en sí, tales como memoria caché interna/galletas vencimientos, no se verán afectados por estos cambios.
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');
}
}
El uso de esto es simple:
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
}
}
usted no aceptó una respuesta aún. ¿Puedes aclarar qué es lo que estás buscando en una respuesta y por qué las respuestas dadas no te satisfacen? – Gordon
Tenía exactamente el mismo problema, la extensión php timecop de la respuesta de @shouze funcionaba como un amuleto. –