Pregunta

Para los objetos que componen otro objeto como parte de su aplicación, ¿cuál es la mejor manera de escribir la prueba de la unidad por lo que sólo el objeto principal se hace la prueba? ejemplo trivial:

class myObj { 
    public function doSomethingWhichIsLogged()
    {
        // ...
        $logger = new logger('/tmp/log.txt');
        $logger->info('some message');
        // ...
    }
}

Yo sé que el objeto podría ser diseñado de manera que la relación de objetos registrador podría inyectarse y por lo tanto se burló en una prueba de unidad, pero eso no es siempre el caso - en los escenarios más complicados, sí es necesario para componer otros objetos o realizar llamadas a métodos estáticos.

Como no queremos poner a prueba el objeto registrador, sólo el myObj, ¿cómo proceder? ¿Creamos un apagó "doble" con el script de prueba? Algo así como:

class logger
{
    public function __construct($filepath) {}
    public function info($message) {}
}

class TestMyObj extends PHPUnit_Framework_TestCase 
{
    // ...
}

Esto parece factible para objetos pequeños, pero sería un dolor para las API más complicados donde el SUT dependía de los valores de retorno. También, si lo desea probar las llamadas al objeto de dependencia de la misma era que puede con los objetos de imitación? ¿Hay una manera de burlarse de objetos que se crean instancias por el SUT en lugar de ser aprobada en?

He leído la página del manual de burla, pero no parece cubrir esta situación en la que la dependencia está compuesta en lugar de agregados. ¿Cómo lo haces?

¿Fue útil?

Solución

A medida que parecen ser conscientes ya, Hormigón Clase Dependencias hace que las pruebas duro (o directamente imposible). Es necesario para desacoplar dicha dependencia. Un simple cambio, que no se rompa la API existente, es por defecto el comportamiento actual, pero proporcionan un gancho para anularlo. Hay un número de maneras en que esto se podría implementar.

Algunas lenguas tienen herramientas que pueden inyectar clases simuladas en el código, pero no sé de algo como esto para PHP. En la mayoría de los casos, es probable que sea mejor refactorización su código de todos modos.

Otros consejos

Tras troelskn asesorar aquí hay un ejemplo básico de lo que debe hacer.

<?php

class MyObj
{
    /**
     * @var LoggerInterface
     */
    protected $_logger;

    public function doSomethingWhichIsLogged()
    {
        // ...
        $this->getLogger()->info('some message');
        // ...
    }

    public function setLogger(LoggerInterface $logger)
    {
        $this->_logger = $logger;
    }

    public function getLogger()
    {
        return $this->_logger;
    }
}


class MyObjText extends PHPUnit_Framework_TestCase
{
    /**
     * @var MyObj
     */
    protected $_myObj;

    public function setUp()
    {
        $this->_myObj = new MyObj;
    }

    public function testDoSomethingWhichIsLogged()
    {
        $mockedMethods = array('info');
        $mock = $this->getMock('LoggerInterface', $mockedMethods);
        $mock->expects($this->any())
             ->method('info')
             ->will($this->returnValue(null));

        $this->_myObj->setLogger($mock);

        // do your testing
    }
}

Más información acerca de los objetos de imitación se puede encontrar rel="noreferrer"> .

En realidad, hay un tiempo razonablemente nueva extensión de sobrecarga clase PHP liberado por los mismos chicos que construyen PHPUnit. Se permite anular el nuevo operador en los casos en que no se puede refactorizar el código, por desgracia, no es así de sencilla de instalar en Windows.

El URL es http://github.com/johannes/php -test-ayudantes / burbuja / maestro /

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top