Testando Classes Abstratas


Respostas:


240

O teste de unidade de classes abstratas não significa necessário testar a interface, pois as classes abstratas podem ter métodos concretos e esses métodos concretos podem ser testados.

Não é tão incomum, ao escrever um código de biblioteca, ter certa classe base que você espera estender na camada de aplicativos. E se você quiser garantir que o código da biblioteca seja testado, precisará de meios para UT os métodos concretos das classes abstratas.

Pessoalmente, eu uso o PHPUnit e ele chama stubs e objetos simulados para ajudá-lo a testar esse tipo de coisa.

Diretamente do manual do 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());
    }
}

O objeto simulado oferece várias coisas:

  • você não é obrigado a ter uma implementação concreta da classe abstrata e pode se safar do stub
  • você pode chamar métodos concretos e afirmar que eles funcionam corretamente
  • se o método concreto se basear no método não implementado (abstrato), você pode stub o valor de retorno com o método will () PHPUnit

38

Esta é uma boa pergunta. Eu também estava procurando por isso.
Felizmente, o PHPUnit já possui um getMockForAbstractClass()método para este caso, por exemplo

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

Importante:

Note que isso requer PHPUnit> 3.5.4. Houve um erro nas versões anteriores.

Para atualizar para a versão mais recente:

sudo pear channel-update pear.phpunit.de
sudo pear upgrade phpunit/PHPUnit

Parece interessante, mas você estaria testando contra o mock? Como seriam os testes? IE: estendendo a simulação no caso de teste e testando contra a classe de teste estendida?
21411 stefgosselin

34

Deve-se notar que, a partir do PHP 7 , foi adicionado suporte para classes anônimas . Isso fornece uma avenida adicional para a configuração de um teste para uma classe abstrata, que não depende da funcionalidade específica do 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
}

4
Obrigado por isso! Usar uma classe anônima no PHPUnit me deu muita flexibilidade na criação de meus vários testes.
Alice maravilha

1

Eran, seu método deve funcionar, mas vai contra a tendência de escrever o teste antes do código real.

O que eu sugeriria é escrever seus testes na funcionalidade desejada de uma subclasse não abstrata da classe abstrata em questão, depois escrever a classe abstrata e a subclasse de implementação e, finalmente, executar o teste.

Seus testes devem obviamente testar os métodos definidos da classe abstrata, mas sempre através da subclasse.


Encontro como resposta arbitrária: Você tem uma classe abstrata 'A' com um método 'foo ()' comum. Esse método 'foo ()' está sendo usado no geral em todas as classes 'B' e 'C', ambas derivadas de 'A'. Qual classe você escolheria testar 'foo ()'?
user3790897

1

A resposta de Nelson está errada.

As classes abstratas não exigem que todos os seus métodos sejam abstratos.

Os métodos implementados são os que precisamos testar.

O que você pode fazer é criar uma classe de stub falsa no arquivo de teste da unidade, estender a classe abstrata e implementar apenas o necessário, sem nenhuma funcionalidade, é claro, e testá-lo.

Felicidades.


0

Se você não deseja subclassificar a classe abstrata apenas para executar um teste de unidade nos métodos já implementados na classe abstrata, tente verificar se sua estrutura permite zombar de classes abstratas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.