如何对Zend控制台提示进行单元测试。单元测试当前等待用户响应

时间:2014-07-28 16:16:16

标签: php zend-framework phpunit

我使用zend 2.2和zend / console来创建cli脚本。该脚本提示用户输入名称或电子邮件地址等信息,并使用以下代码

$name = Line::prompt('Enter Name: ', false, 100);

当用户使用脚本时,这可以正常工作。

我的问题是尝试对此进行单元测试。此时,当我在单元测试中调用调度时,它只是挂起并等待用户输入响应。显然这是一个问题。

我的代码是:

public function testCliScript()
{   
    $consoleMock = $this->getConsoleMock();
    $consoleMock->expects($this->any())->method('writeLine');

    $this->dispatch('run cli--name=test --email=test@example.com');
}

最终调用

protected function getName()
{
    $name = $this->getRequest()->getParam('name');
    $nameOk = !empty($name);

    while (!$nameOk) {
        $nameOk = false;
        $name = Line::prompt('Enter Name: ', false, 100);
        // tie into filter
        if (strlen($name) < 1) {
            $this->getConsole()->writeLine('Name is Too Short');
            continue;
        }

        $nameOk = true;
    };


    return $name;
}

如果有人对如何测试这一点有任何建议,我们将不胜感激。

谢谢

1 个答案:

答案 0 :(得分:1)

这是Dipendency Inversion Principle:testability的主要论据之一。

你的提示对象是你的SUT的硬依赖,因此,要正确测试SUT,你需要将两者分离。

通过构造函数使用Dependency Injection的示例:

// uses omitted for brevity
class SomeController extends AbstractConsoleController
{
    protected $namePrompt;

    public function __construct(PromptInterface $namePrompt)
    {
        $this->namePrompt = $namePrompt;
    }

    protected function getName()
    {
        // etc etc
        $name = $this->namePrompt->show();

    }
}

所以你可以在测试中注入一个提示模拟:

// uses omitted for brevity
class SomeControllerTest extends TestCase
{
    protected $controller;

    protected $namePromptMock;

    public function setUp()
    {
        // etc etc
        $this->namePromptMock = $this->getMock(PromptInterface::class);
        $this->controller     = new SomeController($this->namePromptMock);
        // etc etc
    }

    public function testSomeAction()
    {
        $this->namePromptMock->expects($this->atLeastOnce())
                             ->method('show')
                             ->willReturn('a fake name');

        // dispatch, assertions on the response, etc etc
    }
}

还有其他方法可以实现依赖倒置,即在这种情况下控制器可能需要一大堆提示,因此不是注入每个提示实例(这是不方便和丑陋),你可以使用一个小插件管理器作为一个服务定位器,或使用某种工厂,你可以轻松地模拟这样的抽象,以便它在被问到时只返回提示模拟。