简体   繁体   English

将PHPUnit依赖项注入到TestCase中

[英]PHPUnit Dependency Injection Into A TestCase

I was wondering whether it's possible to inject dependencies into classes derived from PHPUnit_Framework_TestCase via eg some context test suite - in a manner that PHPUnit could handle irregardless whether it has been invoked manually, with a phpunit.xml configuration file or else? 我想知道是否有可能通过例如某些上下文测试套件将依赖项注入到从PHPUnit_Framework_TestCase派生的类中,这种方式使得PHPUnit可以处理无论是否已使用phpunit.xml配置文件手动调用它的方式?

Please consider the following example: 请考虑以下示例:

<?php
interface AnyGreeter {   
    public function greet($recipient);
}   

class FriendlyGreeter implements AnyGreeter {   
    public function greet($recipient) {   
        return "Hello {$recipient}!";
    }   
}   

class DorkGreeter implements AnyGreeter {
    public function greet($recipient) {   
        return "Get lost, {$recipient}!";
    }   
}

Now I want to provide some general test for classes implementing AnyGreeter , eg: 现在,我想为实现AnyGreeter类提供一些常规测试,例如:

<?php
class GeeterTest extends PHPUnit_Framework_TestCase {

    public function testGreet() {   
        $greeter = $this->getGreeter();
        $message = $greeter->greet("world");
        $this->assertContains("world", $message);
    }   

    public function setGreeter(AnyGreeter $greeter) {   
        $this->greeter = $greeter;
    }   

    public function getGreeter() {   
        if (null === $this->greeter) {
            $this->markTestSkipped("No greeter provided");
        }   
        return $this->greeter;
    }

    private $greeter;
} 

This may get re-used by my own as well as any future implementations (which I do not control). 这可能会被我自己以及任何将来的实现(我无法控制)重新使用。

How is this possible, especially in a project that relies on interfaces heavily? 这怎么可能,尤其是在严重依赖接口的项目中? I don't want to write abstract tests and extend them for every single implementation -- 我不想编写抽象测试并将其扩展到每个实现中-

Thanks! 谢谢!

I have never seen this done, and there's nothing in the docs. 我从未见过这样做,文档中也没有任何内容。 Seems a bit complex for a test. 测试似乎有点复杂。 I'd solve your problem by using a data provider to pass greeter objects to the testGreeter method, then all you have to do is maintain an array of concrete greeter classes in the provider. 我可以通过使用数据提供程序将greeter对象传递给testGreeter方法来解决您的问题,然后您所要做的就是在提供程序中维护一系列具体的greeter类。

See the 'data provider' section here: http://www.phpunit.de/manual/3.2/en/writing-tests-for-phpunit.html 请参阅此处的“数据提供者”部分: http : //www.phpunit.de/manual/3.2/en/writing-tests-for-phpunit.html

I think your best approach would use providers as mentioned by Glen: 我认为您最好的方法是使用Glen提到的提供程序:

class GreeterTestCase extends PHPUnit_Framework_TestCase
{
    protected function getGreeter()
    {   
    }   

    /** 
     * @dataProvider providerGreeter
     */
    public function testGreet(AnyGreeter $greeter)
    {   
        $message = $greeter->greet('world');
        $this->assertType('string', $message, 'AnyGreeter::greet() must return string');
        $this->assertContains('world', $message);
    }   

    public function providerGreeter()
    {   
        return array(array($this->getGreeter()));
    }   
}

This way, other parts of the library can extend this test case to test their own implementation meets the basic interface spec. 这样,库的其他部分可以扩展此测试用例,以测试其自己的实现是否符合基本接口规范。 Any of their custom unit tests specific to that implementation go in the extended test case. 他们特定于该实现的任何自定义单元测试都在扩展测试用例中进行。

Now you have a choice of testing a single implementation (which may have its own unit tests), or just grouping together a load of implementations to get the default tests: 现在,您可以选择测试单个实现(可能具有自己的单元测试),也可以将一组实现组合在一起以获取默认测试:

class AnyGreeterTestCase extends GreeterTestCase
{
    public function providerGreeter()
    {
        return array(
            array(new FriendlyGreeter()),
            array(new DorkGreeter()),
        );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM