PHPUnit - 为接口编写测试类,并使用工厂测试对象

时间:2011-12-23 14:52:20

标签: php unit-testing oop phpunit

我正在编写一个将继承接口的类。将为该接口编写客户端代码,并编写用于支持它的类。我的想法是稍后我将为该接口编写其他类,这两个不同类的对象应该是完全可互换的。我没有为第一个类编写测试类,而是想为接口编写一个。

我的计划是编写一个测试类,它将构造函数的一个工厂对象(依赖注入),并使用工厂创建被测试类的新实例。

这样,如果我想测试ClassA,我可以将ClassAFactory对象传递给测试类的构造函数,如果我想测试ClassB,我会传递一个ClassBFactory对象。这两个类都是可以互换的,因为只有公共方法应该被测试,这似乎是理想的。

但是测试构造函数怎么样?我是否会更好地编写一个抽象的测试类,并在继承抽象测试类的类中实现构造函数测试(不同的类可能会以不同的方式实例化)?

如果我确实使用了第一个想法,我想我会为每个正在测试的类提供测试类,例如:

class ClassATest extends [PHPUnit test case]
{
    $myFactory = new ClassAFactory();
    $myTest = new ClassTest($myFactory);

    $myTest->test1();
    $myTest->test2();
    //etc.
}

最好的方法是什么?我想要进行一般性测试,这样当我编写新类来实现公共接口时,我可以只使用与其他测试相同的测试对象。但是,看到不同的类会有不同的构造函数,或许编写一个抽象的测试类并为每个新对象扩展它会更好吗?你觉得怎么样?

2 个答案:

答案 0 :(得分:7)

我认为您需要重新考虑您的计划。您无法测试接口,这是一个很好的理由 - 接口只定义API而不是功能,测试测试功能。让我举一个可能有帮助的例子。假设您有一个“消息”界面。因此,您实现了EmailMessager和SMSMessager。现在你需要像EmailMessager一样单独测试这些,你需要确保它正在做它的东西,可能验证收件人(一个电子邮件地址),并可能将发送委托给一个电子邮件类等。显然,SMS消息会有所不同。

答案 1 :(得分:6)

您可以使用每个子类将设置的属性创建一个包含所有测试方法的抽象测试用例,而无需工厂。它可以测试所有实现必须具备的固定质量。

abstract class IAdderTestCase extends PFTC
{
    function testAdd() {
        self::assertEquals(5, $this->fixture->add(2, 3));
    }
    ...
}

class BasicAdderTest extends IAdderTestCase
{
    function setUp() {
        $this->fixture = new BasicAdder();
    }
}

PHPUnit将在每个测试方法之前调用setUp()。它应该调用每个具体子类的所有继承测试方法以及任何其他子类,例如测试构造函数。