Estoy tratando de agregar pruebas unitarias a una clase que usa Memcache como un servicio para obtener y almacenar claves en el demonio local de Memcached.
Mi problema es que, aunque el código funciona bien, cuando intento simular la clase Memcache y se llama al método get(), aparece este tipo de error:
ArgumentCountError: Muy pocos argumentos para la función Mock_Memcache_b25e34cb::get(), se pasó 1 en /path/to/file.php en la línea 64 y se esperaban exactamente 3
Sospeché un error de reflexión, así que probé un pequeño script para probarlo:
<?php $class = new ReflectionClass(Memcache::class); $getMethod = $class->getMethod('get'); $getParams = $getMethod->getParameters(); foreach($getParams as $param) { var_dump((string) $param); }La salida que obtengo es
string(35) "Parámetro #0 [ $param0 ]"
string(36) "Parámetro #1 [ &$param1 ]"
string(36) "Parámetro #2 [ &$param2 ]"
Sin embargo, la documentación que se encuentra en el documento oficial de PHP establece que la firma debe ser:
Memcache::get(string $key, int &$flags = ?): stringo
Memcache::get(array $keys, array &$flags = ?): array¿Cómo se puede explicar la discrepancia? ¿Por qué mi código funciona bien en producción pero falla en UT? ¿Hay alguna forma de resolver este problema que no sea crear mi propia clase simulada para Memcache? ¡Gracias!
FYI, mi método actual para obtener el simulacro es este:
protected function createMock($originalClassName) { return $this->getMockBuilder($originalClassName) ->disableOriginalConstructor() ->disableOriginalClone() ->disableArgumentCloning() ->disallowMockingUnknownTypes() ->getMock(); } public function existsReturnsTrueOrFalse($value, $expected) { $memcacheMock = $this->createMock(\Memcache::class); ... }¿Cómo se puede explicar la discrepancia?
La mayoría de las veces esto es solo que la documentación no está actualizada con la extensión.
Otra explicación puede ser un error con el reflejo de las bibliotecas.
Al ver el resultado del reflejo, diría que los documentos están más actualizados que el reflejo.
¿Por qué mi código funciona bien en producción pero falla en UT?
La diferencia entre la producción y la ejecución de prueba de sus pruebas unitarias para su pregunta es la creación del simulacro: en producción, no crea el simulacro y, por lo tanto, no falla.
¿Hay alguna forma de resolver este problema que no sea crear mi propia clase simulada para Memcache?
En realidad, crear tu propia clase simulada no parece una mala idea. Sin embargo, podría considerar pensar un paso más allá:
En este momento, el código de producción tiene la clase Memcache como dependencia. Sus pruebas ya le muestran que la interfaz es inestable, la dependencia rechaza la prueba (con sus herramientas estándar como los simulacros).
Por razones como esta y otras, a menudo se recomienda empaquetar bibliotecas de terceros. Tal vez sea un caso extremo aquí, ya que está relacionado con una extensión de PHP que probablemente no sea tan volátil, pero tal vez el envoltorio le brinde más espacio para el desarrollo, las pruebas y el mantenimiento.
Puede extraer la parte de la interfaz pública de la clase Memcache que utiliza en una interfaz en sí, por ejemplo, MemcacheInterface . Luego, puede crear una clase envolvente liviana que implemente la interfaz y, bajo el capó, delegue las llamadas al método a una instancia de Memcache .
Luego reemplaza el objeto de Memcache en el código de producción con el objeto de su contenedor y escribe sugerencias de Memcache con su interfaz MemcacheInterface .
En las pruebas creas el simulacro desde la interfaz.
Esta voluntad