代码之家  ›  专栏  ›  技术社区  ›  Mez

测试抽象类

  •  159
  • Mez  · 技术社区  · 17 年前

    如何使用PHPUnit测试抽象类的具体方法?

    我希望我必须创建某种对象作为测试的一部分。不过,我不知道最好的做法是什么,也不知道PHPUnit是否允许这样做。

    6 回复  |  直到 13 年前
        1
  •  250
  •   Ionuț Staicu    11 年前

    抽象类的单元测试并不一定意味着测试接口,因为抽象类可以有具体的方法,而这些具体的方法是可以测试的。

    在编写一些库代码时,拥有希望在应用层中扩展的特定基类并不罕见。如果你想确保库代码经过测试,你需要对抽象类的具体方法进行UT。

    就我个人而言,我使用PHPUnit,它有所谓的存根和模拟对象来帮助你测试这类东西。

    直接从 PHPUnit manual :

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

    Mock对象为您提供了几件事:

    • 你不需要有抽象类的具体实现,可以用存根代替
    • 您可以调用具体方法并断言它们执行正确
    • 如果具体方法依赖于未实现的(抽象)方法,则可以使用will()PHPUnit方法来存根返回值
        2
  •  39
  •   GordonM    7 年前

    需要注意的是,从PHP 7开始支持 anonymous classes 已添加。这为您提供了为抽象类设置测试的额外途径,该途径不依赖于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
    }
    
        3
  •  39
  •   chiborg Alessandro Minoccheri    7 年前

    这个问题问得好。我也一直在找这个。
    幸运的是,PHPUnit已经 getMockForAbstractClass() 这种情况下的方法,例如。

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

    重要提示:

    请注意,这需要PHPUnit> 3.5.4.有 a bug 在以前的版本中。

    要升级到最新版本:

    sudo pear channel-update pear.phpunit.de
    sudo pear upgrade phpunit/PHPUnit
    
        4
  •  1
  •   Bruno Bruno    17 年前

    Eran,你的方法应该有效,但这与在实际代码之前编写测试的趋势背道而驰。

    我建议对所讨论的抽象类的非抽象子类的所需功能编写测试,然后编写抽象类和实现子类,最后运行测试。

    你的测试显然应该测试抽象类的定义方法,但总是通过子类。

        5
  •  1
  •   skqr    16 年前

    Nelson的回答是错误的。

    抽象类并不要求它们的所有方法都是抽象的。

    实现的方法是我们需要测试的方法。

    你能做的就是在单元测试文件上创建一个假存根类,让它扩展抽象类,只实现所需的东西,当然,没有任何功能,然后进行测试。

    干杯。

        6
  •  0
  •   hangy    17 年前

    如果你不想为了对抽象类中已经实现的方法执行单元测试而对抽象类进行子类化,你可以试着看看你的框架是否允许你 mock 抽象类。