【问题标题】:How to unit test Zend Console Prompt. Unit test currently waits for user response如何对 Zend 控制台提示进行单元测试。单元测试当前等待用户响应
【发布时间】:2014-09-19 21:30:35
【问题描述】:

我正在使用 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;
}

如果有人对如何测试有任何建议,将不胜感激。

谢谢

【问题讨论】:

    标签: php zend-framework phpunit


    【解决方案1】:

    这是Dipendency Inversion Principle 的主要论据之一:可测试性。

    您的提示对象是您的 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
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-23
      • 2012-01-08
      • 1970-01-01
      • 2013-09-16
      • 2019-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多