추상 클래스 테스트


144

PHPUnit으로 추상 클래스의 구체적인 메소드를 어떻게 테스트합니까?

테스트의 일부로 일종의 객체를 만들어야한다고 기대합니다. 그래도, 이것에 대한 최선의 방법이나 PHPUnit이 이것을 허용하는지 모르겠습니다.


10
아마도 당신은 수락 된 답변을 변경하는 것을 고려해야합니다.
Jacob

1
아마 stackoverflow.com/a/2947823/23963 이 도움이 될 것입니다.
Nigel Thorne 1

답변:


240

추상 클래스의 단위 테스트는 인터페이스를 테스트하는 것을 의미하지 않습니다. 추상 클래스는 구체적인 메소드를 가질 수 있으며이 구체적인 메소드는 테스트 할 수 있습니다.

일부 라이브러리 코드를 작성할 때 응용 프로그램 계층에서 확장 할 것으로 예상되는 특정 기본 클래스를 갖는 것은 그리 드문 일이 아닙니다. 라이브러리 코드가 테스트되도록하려면 추상 클래스의 구체적인 메소드를 유추해야합니다.

개인적으로, PHPUnit을 사용하는데, 이런 종류의 것들을 테스트하는 데 도움이되는 스텁과 모의 객체가 있습니다.

직선에서 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());
    }
}

모의 객체는 몇 가지를 제공합니다.

  • 추상 클래스를 구체적으로 구현할 필요는 없으며 대신 스텁으로 벗어날 수 있습니다.
  • 구체적인 메소드를 호출하고 올바르게 수행한다고 주장 할 수 있습니다.
  • 구체적인 메소드가 구현되지 않은 (추상적 인) 메소드에 의존하는 경우 will () PHPUnit 메소드를 사용하여 리턴 값을 스텁 할 수 있습니다.

38

그건 좋은 질문이야. 나도 이것을 찾고 있었다.
운 좋게도 PHPUnit에는 이미이 getMockForAbstractClass()경우에 대한 메소드가 있습니다.

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

중대한:

PHPUnit> 3.5.4가 필요합니다. 이전 버전 에는 버그 가있었습니다 .

최신 버전으로 업그레이드하려면

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

흥미롭게 들리지만 모의 테스트를하고 있습니까? 테스트는 어떻습니까? IE : 테스트 케이스에서 모의를 확장하고 확장 테스트 클래스에 대해 테스트합니까?
stefgosselin

34

PHP 7 부터 익명 클래스에 대한 지원 이 추가되었습니다. 이것은 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
감사합니다! PHPUnit에서 익명 클래스를 사용하면 다양한 테스트를 만들 때 많은 유연성을 얻었습니다.
Alice Wonder

1

Eran, 당신의 방법은 작동해야하지만 실제 코드 전에 테스트를 작성하는 경향에 위배됩니다.

내가 제안하는 것은 문제의 추상 클래스의 비추 상 서브 클래스의 원하는 기능에 대한 테스트를 작성한 다음 추상 클래스와 구현 서브 클래스를 작성하고 마지막으로 테스트를 실행하는 것입니다.

테스트는 분명히 추상 클래스의 정의 된 메소드를 테스트해야하지만 항상 서브 클래스를 통해 수행해야합니다.


나는 임의의 답으로 찾았습니다 : 당신은 공통 'foo ()'메소드를 갖는 추상 클래스 'A'를 가지고 있습니다. 이 'foo ()'메소드는 전반적으로 모든 'B'및 'C'클래스가 모두 'A'에서 파생됩니다. 어떤 클래스를 'foo ()'테스트하기로 선택 하시겠습니까?
user3790897

1

넬슨의 대답이 잘못되었습니다.

추상 클래스는 모든 메소드가 추상 일 필요는 없습니다.

구현 된 메소드는 테스트해야합니다.

당신이 할 수있는 일은 단위 테스트 파일에 가짜 스텁 클래스를 만들고 추상 클래스를 확장하고 기능이 전혀 필요없는 것만 구현하고 테스트하는 것입니다.

건배.


0

추상 클래스에서 이미 구현 된 메소드에 대해 단위 테스트를 수행하기 위해 추상 클래스를 서브 클래 싱하지 않으려는 경우 프레임 워크에서 추상 클래스 를 조롱 할 수 있는지 여부를 확인할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.