PHPUnit模拟视图助手ZF2

3

我创建了一个视图助手:

class SousMenuContrat extends AbstractHelper
{
    private $maiContratService;

    public function __construct(
        FMaiContratService $maiContratService,
    ) {
        $this->maiContratService                = $maiContratService;
    }

    public function __invoke($iMaiContratId, $sActive)
    {
        $oContrat = $this->maiContratService->selectById($iMaiContratId);

        return $this->getView()->partial('maintenance/sousmenucontrat', array(
            'oContrat'         => $oContrat
        ));
    }
}

现在我需要使用PHPUnit进行测试:

class SousMenuContratTest extends TestCase
{
    private $myService;

    public function setUp()
    {
        $maiContratService = $this->getMockBuilder('Maintenance\Service\Model\FMaiContratService')
            ->disableOriginalConstructor()
            ->getMock();

        $oContrat = new FMaiContrat();
        $stub = $this->returnValue($oContrat);
        $maiContratService->expects($this->any())->method('selectById')->will($stub);
        $this->myService = new SousMenuContrat(
            $maiContratService
        );
    }

    public function testInvoque()
    {
        $this->myService->__invoke(2, 'contrat');
    }
}

但是测试会发送错误,因为测试不知道:

$this->getView()->partial();

提前感谢 :)


未来项目建议:不要用母语命名类等。将整个代码保持在英文状态是一个好习惯。这样,每个人都可以理解它,并且因为所有函数也都是英文的,你的代码中只有一种语言。(我们的学员总是在他们的代码中使用德语而遇到麻烦;-)) - StoryTeller
我知道,但这是内部惯例 :) - Amelie
2个回答

3

在你的测试中,你需要模拟 getView() 返回的渲染器:

    /** @var PhpRenderer|\PHPUnit_Framework_MockObject_MockObject $rendererMock */
    $rendererMock = $this->getMockBuilder('Zend\View\Renderer\PhpRenderer')
        ->disableOriginalConstructor()
        ->getMock();
    $rendererMock->expects($this->once())
        ->method("partial")
        ->with(array(
            'maintenance/sousmenucontrat',
            array('oContrat' => new FMaiContrat()),
        ));
    $this->myService->setView($rendererMock);

最好的解决方案是在setUp()函数中实例化的FMaiContrat对象也在with()函数中使用,但在这种情况下,这个方法同样适用。

编辑: 完整的测试代码如下所示:

class SousMenuContratTest extends TestCase
{
    private $myService;

    public function setUp()
    {
        $maiContratService = $this->getMockBuilder('Maintenance\Service\Model\FMaiContratService')
            ->disableOriginalConstructor()
            ->getMock();

        $oContrat = new FMaiContrat();
        $stub = $this->returnValue($oContrat);
        $maiContratService->expects($this->any())->method('selectById')->will($stub);
        $this->myService = new SousMenuContrat(
            $maiContratService
        );
    }

    public function testInvoque()
    {
        /** @var PhpRenderer|\PHPUnit_Framework_MockObject_MockObject $rendererMock */
        $rendererMock = $this->getMockBuilder('Zend\View\Renderer\PhpRenderer')
            ->disableOriginalConstructor()
            ->getMock();
        $rendererMock->expects($this->once())
            ->method("partial")
            ->with(array(
                'maintenance/sousmenucontrat',
                array('oContrat' => new FMaiContrat()),
            ));
        $this->myService->setView($rendererMock);
        $this->myService->__invoke(2, 'contrat');
    }
}

抱歉,但我遇到了失败 :(1)MaintenanceTest\Service\Model\SousMenuContratTest::testInvoque 当调用1次时,期望方法名称等于string:partial。 预期该方法将被调用1次,实际上却未被调用。 - Amelie
1
好的,这意味着模拟测试有效;-) 我编辑了我的答案,完整的代码可能会有所帮助。 - StoryTeller
我需要看到你的代码,但进一步调试问题不是回答的目的。我为此事开了一个聊天室: http://chat.stackoverflow.com/rooms/91564/room-for-amelie-and-storyteller 请在那里粘贴你的辅助和测试代码。 - StoryTeller

2
如果您只想使用ZF2类并在SousMenuContrat构造函数中模拟依赖项,则可以使用以下设置。
protected function setUp()
{
   $maiContratService = $this->getMockBuilder('Maintenance\Service\Model\FMaiContratService')
        ->disableOriginalConstructor()
        ->getMock();

    $oContrat = new FMaiContrat($maiContratService);
    $stub = $this->returnValue($oContrat);
    $maiContratService->expects($this->any())->method('selectById')->will($stub);

    Doctype::unsetDoctypeRegistry();

    $this->helper = new SousMenuContrat();
    $this->renderer = new PhpRenderer;
    $this->viewHelperManager = $this->renderer->getHelperPluginManager();
    $config  = new HelperConfig();
    $config->configureServiceManager($this->viewHelperManager);
    $this->helper->setView($this->renderer);

    parent::setUp();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接