Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHPUnit-为接口编写测试类,并使用工厂测试对象_Php_Unit Testing_Oop_Phpunit - Fatal编程技术网

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

PHPUnit-为接口编写测试类,并使用工厂测试对象,php,unit-testing,oop,phpunit,Php,Unit Testing,Oop,Phpunit,我正在编写一个将继承接口的类。将为该接口编写客户端代码,并编写支持该接口的类。我的想法是,稍后我将为该接口编写其他类,这两个不同类的对象应该完全可以互换。我想为接口编写一个测试类,而不是为第一个类编写一个测试类 我的计划是编写一个测试类,该类将接受构造函数的工厂对象(依赖项注入),并使用工厂创建被测试类的新实例 这样,如果我想测试ClassA,我可以将ClassAFactory对象传递给测试类的构造函数,如果我想测试ClassB,我将传递ClassBFactory对象。这两个类都被设计成可互换的

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

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

这样,如果我想测试ClassA,我可以将ClassAFactory对象传递给测试类的构造函数,如果我想测试ClassB,我将传递ClassBFactory对象。这两个类都被设计成可互换的,而且因为只有公共方法应该被测试,这看起来很理想

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

如果我真的使用了第一个想法,我想我会为每个被测试的类设置一个测试类,比如:

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

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

最好的办法是什么?我希望有一个通用测试,这样当我编写新类来实现公共接口时,我就可以放置一个与其他测试相同的测试对象。但是,考虑到不同的类会有不同的构造函数,也许编写一个抽象测试类并为每个新对象扩展它会更好?你觉得怎么样?

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

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

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()。它应该为每个具体的子类调用所有继承的测试方法,再加上任何附加的方法,例如测试构造函数。

在这个特定的示例中,这些类将表示邮件列表的收件人。尽管他们有不同的工作方式,但他们会从客户机获取相同的数据,并返回相同的结果——完全可以互换。在我看来,如果使用该接口的不同类的对象在客户机代码中是可互换的,那么它们在测试代码中也应该是可互换的。所以,当我说我想测试接口时,我的意思是,我想对该接口编写一个测试,以便测试使用该接口的类。这对你有意义吗?没有,还是没有意义。这不是我理解界面工作的方式。您可能需要一个抽象基类而不是一个接口来实现公共代码。我不确定除了数据之外,您的类还有什么不同。比如说,在类中,MailChimpRecipient使用MailingListRecipient接口:客户端通过设置收件人对象的电子邮件地址和名称属性,然后调用一个方法将某人添加到列表中。现在,MailChimp类的方法将使用MailChimp API添加它们。假设将来,我想托管自己的邮件列表或使用另一个提供程序,我可以将该类切换到另一个使用MailingListRecipient接口的类。该类可能会做一些完全不同的事情来添加收件人,但它仍然需要相同的数据。这基本上是我的观点。添加电子邮件地址和名称属性的方法对于所有邮件列表都是通用的,因此它们可以很好地位于抽象基类中。将收件人对象添加到您正在使用的任何邮件列表提供程序的方法都适合一个接口,但正如您所指出的,该方法的功能将取决于您正在使用的邮件列表,因此需要单独测试。我认为您对该词的两个稍有不同的含义感到困惑接口。接口(在API中)是类的公共方法,因此和对象公开。人们常说这是您应该测试的,尽管您实际上正在测试每个方法背后的功能。有测试受保护和私有方法的方法,测试这些方法也有一些好处。接口这个词的另一个含义是PHP结构,它定义了一组实现接口的类必须实现的通用方法。谢谢!这似乎是最好的方法,因为我可以为每个不同的子类更改设置方法。