Mejores prácticas para probar métodos protegidos con PHPUnit (en clases abstractas)

Con PHPUnit y PHP> = 5.3 es posible probar métodos protegidos. La siguiente página en stackoverflow describió las mejores prácticas en ella:

“Mejores prácticas para probar métodos protegidos con PHPUnit”

protected static function callProtectedMethod($name, $classname, $params) { $class = new ReflectionClass($classname); $method = $class->getMethod($name); $method->setAccessible(true); $obj = new $classname($params); return $method->invokeArgs($obj, $params); } 

Probar métodos públicos en clases abstractas es fácil con PHPUnit. Probar métodos protegidos en clases normales es fácil con el enfoque anterior. Para probar los métodos protegidos en clases abstractas debe ser posible de alguna manera …

Sé que PHPUnit deriva clases abstractas y “implementa” métodos abstractos en una clase concreta y dispara las pruebas contra esa clase concreta, pero no sé cómo integrar eso en el enfoque anterior para tener una llamadaProtectedMethodOnAbstractClasses ().

¿Cómo estás haciendo tales pruebas?

PD: La pregunta NO es acerca de la verdad de probar métodos protegidos (ver: pruebas de blanco, gris y blackbox). La necesidad de probar métodos protegidos depende de su estrategia de prueba.

Como está pidiendo una ‘mejor práctica’, tomaré un enfoque diferente para responder:

No pruebe métodos privados y protegidos

El hecho de que puedas no significa que debas.

Quieres probar que una clase funciona. Eso significa que todas las funciones que puede invocar (todo público) devuelven los valores correctos (y tal vez llamar a las funciones correctas en los objetos pasados) y nada más .

No te importa cómo se implementa esto en la clase.

Incluso te duele escribir pruebas para cualquier cosa que no sea pública por dos grandes razones:

  • Hora

Escribir pruebas lleva más tiempo ya que necesita más y la refactorización también lleva más tiempo. Si mueve el código en una clase sin cambiar su comportamiento, no debería actualizar sus pruebas. ¡Las pruebas deberían decirle que todo sigue funcionando!

  • Cobertura de código significativa

Si escribe una prueba para cada método protegido, pierde uno de los beneficios heredados del informe de cobertura del código: no le indicará qué funciones protegidas ya no se llaman . Eso es una cosa mala porque no se prueban correctamente todos los métodos públicos (¿por qué hay un método que no se llama si se prueban todos los casos?) O realmente ya no se necesita ese método, pero ya es “verde”, no lo pienses más.

Para citar al autor de PHPUnit

Entonces: el hecho de que la prueba de atributos y métodos protegidos y privados sea posible no significa que sea una “cosa buena”.

http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html

Dado que el mundo real a veces difiere

...->setAccessible() está bien para los métodos normales

para uso de cosas abstractas ...->getMockForAbstractClass()

Pero por favor hazlo solo si es realmente necesario.

Un método protegido en una clase abstracta se probará probando la API pública de sus hijos de todos modos con mis argumentos de la aplicación anterior.

Suposición: desea llamar a métodos protegidos concretos en una clase abstracta.

Cree un objeto simulado para la clase abstracta y páselo a esta forma modificada de callProtectedMethod() .

 public static function callProtectedMethod($object, $method, array $args=array()) { $class = new ReflectionClass(get_class($object)); $method = $class->getMethod($method); $method->setAccessible(true); return $method->invokeArgs($object, $args); } public function testGetArea() { $rect = $this->getMockForAbstractClass('RandomRectangle'); self::callProtectedMethod($rect, 'setWidth', array(7)); self::callProtectedMethod($rect, 'setHeight', array(3)); self::assertEquals(21, $rect->getArea()); } 

Podría encapsular esto en un único método, pero prefiero pasar el objeto para que una prueba pueda llamar a múltiples métodos protegidos / privados en el mismo objeto. Para hacerlo, use $class->isAbstract() para decidir cómo construir el objeto.

    Intereting Posts