Encontré el debate sobre ¿Prueba método privado informativo.
He decidido que en algunas clases quiero tener métodos protegidos, pero probarlos. Algunos de estos métodos son estáticos y cortos. Debido a que la mayoría de los métodos públicos los utilizan, probablemente pueda eliminar las pruebas de forma segura más adelante. Pero para comenzar con un enfoque TDD y evitar la depuración, realmente quiero probarlos.
Pensé en lo siguiente:
- Método Objeto como se aconseja en una respuesta parece ser excesivo para esto.
- Comience con métodos públicos y cuando la cobertura del código esté dada por pruebas de nivel superior, proteja y elimine las pruebas.
- Herede una clase con una interfaz comprobable que haga públicos los métodos protegidos
¿Cuál es la mejor práctica? ¿Hay algo mas?
Parece que JUnit cambia automáticamente los métodos protegidos para que sean públicos, pero no tuve una mirada más profunda. PHP no permite esto a través de la reflexión .
php
unit-testing
phpunit
GrGr
fuente
fuente
Respuestas:
Si está usando PHP5 (> = 5.3.2) con PHPUnit, puede probar sus métodos privados y protegidos utilizando la reflexión para configurarlos para que sean públicos antes de ejecutar sus pruebas:
fuente
protected
método también es parte de la API pública porque cualquier clase de terceros puede extenderlo y usarlo sin ningún tipo de magia. Así que creo que solo losprivate
métodos entran en la categoría de métodos que no se deben probar directamente.protected
ypublic
debe ser probado directamente.Parece que ya lo sabes, pero lo repetiré de todos modos; Es una mala señal, si necesita probar métodos protegidos. El objetivo de una prueba unitaria es probar la interfaz de una clase, y los métodos protegidos son detalles de implementación. Dicho esto, hay casos en los que tiene sentido. Si usa la herencia, puede ver una superclase como una interfaz para la subclase. Entonces, aquí, tendrías que probar el método protegido (pero nunca un método privado uno ). La solución a esto es crear una subclase para fines de prueba y usarla para exponer los métodos. P.ej.:
Tenga en cuenta que siempre puede reemplazar la herencia con la composición. Cuando se prueba el código, generalmente es mucho más fácil manejar el código que usa este patrón, por lo que es posible que desee considerar esa opción.
fuente
la quemadura tiene el enfoque correcto. Aún más simple es llamar al método directamente y devolver la respuesta:
Puede llamar a esto simplemente en sus pruebas:
fuente
Me gustaría proponer una ligera variación para getMethod () definido en la respuesta de uckelman .
Esta versión cambia getMethod () eliminando valores codificados y simplificando un poco el uso. Recomiendo agregarlo a su clase PHPUnitUtil como en el ejemplo a continuación o a su clase que amplía PHPUnit_Framework_TestCase (o, supongo, globalmente a su archivo PHPUnitUtil).
Como MyClass se está instanciando de todos modos y ReflectionClass puede tomar una cadena o un objeto ...
También creé una función de alias getProtectedMethod () para ser explícito lo que se espera, pero eso depende de usted.
¡Salud!
fuente
Creo que troelskn está cerca. Yo haría esto en su lugar:
Luego, implemente algo como esto:
Luego ejecuta sus pruebas contra TestClassToTest.
Debería ser posible generar automáticamente tales clases de extensión analizando el código. No me sorprendería si PHPUnit ya ofrece dicho mecanismo (aunque no lo he comprobado).
fuente
Voy a tirar mi sombrero al ring aquí:
He usado el hack de __call con diversos grados de éxito. La alternativa que se me ocurrió fue usar el patrón Visitor:
1: generar una clase stdClass o personalizada (para imponer el tipo)
2: imprima eso con el método y los argumentos requeridos
3: asegúrese de que su SUT tenga un método acceptVisitor que ejecutará el método con los argumentos especificados en la clase visitante
4: inyectarlo en la clase que desea evaluar
5: SUT inyecta el resultado de la operación en el visitante
6: aplique sus condiciones de prueba al atributo de resultado del visitante
fuente
De hecho, puede usar __call () de forma genérica para acceder a métodos protegidos. Para poder probar esta clase
creas una subclase en ExampleTest.php:
Tenga en cuenta que el método __call () no hace referencia a la clase de ninguna manera, por lo que puede copiar lo anterior para cada clase con los métodos protegidos que desea probar y simplemente cambiar la declaración de la clase. Es posible que pueda colocar esta función en una clase base común, pero no la he probado.
Ahora, el caso de prueba solo difiere en el lugar donde construye el objeto que se probará, intercambiando en ExampleExposed por Example.
Creo que PHP 5.3 le permite usar la reflexión para cambiar la accesibilidad de los métodos directamente, pero supongo que tendría que hacerlo para cada método individualmente.
fuente
call_user_method_array()
función está en desuso a partir de PHP 4.1.0 ... usecall_user_func_array(array($this, $method), $args)
en su lugar. Tenga en cuenta que si está utilizando PHP 5.3.2+ se puede utilizar la reflexión para obtener acceso a métodos protegidos / privadas y atributosAccessible
paquete genérico que utiliza la reflexión para permitir que las pruebas accedan a propiedades privadas / protegidas y métodos de clases y objetos.__call()
solo se invoca si la persona que llama no tiene acceso al método. Como la clase y sus subclases tienen acceso a los métodos protegidos, las llamadas no se realizarán__call()
. ¿Puedes publicar tu código que no funciona en 5.2.7 en una nueva pregunta? Usé lo anterior en 5.2 y solo pasé a usar la reflexión con 5.3.2.Sugiero la siguiente solución para la solución / idea de "Henrik Paul" :)
Conoces nombres de métodos privados de tu clase. Por ejemplo, son como _add (), _edit (), _delete () etc.
Por lo tanto, cuando desee probarlo desde el aspecto de las pruebas unitarias, simplemente llame a métodos privados con el prefijo y / o sufijo algunos comunes palabra (por ejemplo, _addPhpunit) para que cuando se llame al método __call () (ya que el método _addPhpunit () no existe) de la clase de propietario, solo debe poner el código necesario en el método __call () para eliminar la palabra / s con prefijo / sufijo (Phpunit) y luego llamar a ese método privado deducido desde allí. Este es otro buen uso de los métodos mágicos.
Pruébalo.
fuente