Probando Clases Abstractas


¿Cómo pruebo los métodos concretos de una clase abstracta con PHPUnit?

Esperaría que tuviera que crear algún tipo de objeto como parte de la prueba. Sin embargo, no tengo idea de la mejor práctica para esto o si PHPUnit lo permite.

Author: David Harkness, 2008-10-10

6 answers

Las pruebas unitarias de clases abstractas no necesariamente significan probar la interfaz, ya que las clases abstractas pueden tener métodos concretos, y estos métodos concretos pueden ser probados.

No es tan raro, al escribir algún código de biblioteca, tener cierta clase base que espera extender en su capa de aplicación. Y si desea asegurarse de que el código de la biblioteca se prueba, necesita medios para UT los métodos concretos de clases abstractas.

Personalmente, uso PHPUnit, y tiene tan llamados talones y objetos simulados para ayudarle a probar este tipo de cosas.

Directamente desde Manual de PHPUnit :

abstract class AbstractClass
{
    public function concreteMethod()
    {
        return $this->abstractMethod();
    }

    public abstract function abstractMethod();
}

class AbstractClassTest extends PHPUnit_Framework_TestCase
{
    public function testConcreteMethod()
    {
        $stub = $this->getMockForAbstractClass('AbstractClass');
        $stub->expects($this->any())
             ->method('abstractMethod')
             ->will($this->returnValue(TRUE));

        $this->assertTrue($stub->concreteMethod());
    }
}

Objeto simulado te da varias cosas:

  • no se requiere que tenga una implementación concreta de la clase abstracta, y puede salirse con la suya en su lugar
  • puede llamar a métodos concretos y afirmar que funcionan correctamente
  • si el método concreto se basa en el método no implementado (abstracto), puede extraer el valor devuelto con will() método PHPUnit
 211
Author: Victor Farazdagi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-13 11:40:36

Esa es una buena pregunta. Yo también he estado buscando esto.
Por suerte, PHPUnit ya tiene getMockForAbstractClass() método para este caso, por ejemplo,

protected function setUp()
{
    $stub = $this->getMockForAbstractClass('Some_Abstract_Class');
    $this->_object = $stub;
}

Importante:

Tenga en cuenta que esto requiere PHPUnit > 3.5.4. Hubo un error en versiones anteriores.

Para actualizar a la nueva versión:

sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit
 36
Author: takeshin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-17 10:06:01

Debe tenerse en cuenta que a partir de PHP 7 se ha agregado soporte para clases anónimas. Esto le da una vía adicional para configurar una prueba para una clase abstracta, una que no depende de la funcionalidad específica de PHPUnit.

class AbstractClassTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var AbstractClass
     */
    private $testedClass;

    public function setUp()
    {
        $this->testedClass = new class extends AbstractClass {

            protected function abstractMethod()
            {
                // Put a barebones implementation here
            }
        };
    }

    // Put your tests here
}
 9
Author: GordonM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-20 15:47:01

Eran, su método debería funcionar, pero va en contra de la tendencia de escribir la prueba antes del código real.

Lo que sugeriría es escribir sus pruebas sobre la funcionalidad deseada de una subclase no abstracta de la clase abstracta en cuestión, luego escribir tanto la clase abstracta como la subclase implementadora, y finalmente ejecutar la prueba.

Sus pruebas obviamente deben probar los métodos definidos de la clase abstracta, pero siempre a través de la subclase.

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-12 18:48:10

La respuesta de Nelson es incorrecta.

Las clases abstractas no requieren que todos sus métodos sean abstractos.

Los métodos implementados son los que necesitamos probar.

Lo que puede hacer es crear una clase stub falsa en el archivo de prueba unitaria, hacer que extienda la clase abstracta e implementar solo lo que se requiere sin ninguna funcionalidad, por supuesto, y probarlo.

Salud.
 1
Author: skqr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-23 15:19:58

Si no desea subclasificar la clase abstracta solo para realizar una prueba unitaria sobre los métodos que ya están implementados en la clase abstracta, podría intentar ver si su marco le permite burlarse de clases abstractas.

 0
Author: hangy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-12 19:06:25