PHPUnit, интерфейсы и пространства имен (Symfony2) - PullRequest
5 голосов
/ 16 ноября 2011

В настоящее время я работаю над пакетом с открытым исходным кодом для Symfony2 и очень хочу, чтобы он был собачьим собеседником с точки зрения охвата модульных тестов и общей надежности, однако я столкнулся с трудностью из-за недостатка знаний PHPUnit (или сложный сценарий, кто знает) ..

В настоящее время у меня есть класс Mailer для обработки отдельных почтовых сценариев. Это выглядит примерно так:

<?php
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\Routing\RouterInterface;

class Mailer
{
    protected $mailer;
    protected $router;
    protected $templating;
    protected $parameters;

    public function __construct($mailer, RouterInterface $router, EngineInterface $templating, array $parameters)
    {
        $this->mailer = $mailer;
        $this->router = $router;
        $this->templating = $templating;
        $this->parameters = $parameters;
    }
}

Достаточно просто, есть несколько интерфейсов Symfony2 для работы с различными системами маршрутизации и шаблонов, счастливые счастливые радости радости.

Вот начальный тест, который я пытался настроить для вышеупомянутого:

<?php
use My\Bundle\Mailer\Mailer

class MailerTest extends \PHPUnit_Framework_TestCase
{
    public function testConstructMailer
    {
        $systemMailer = $this->getSystemMailer();
        $router = $this->getRouter();
        $templatingEngine = $this->getTemplatingEngine();

        $mailer = new Mailer($systemMailer, $router, $templatingEngine, array());
    }

    protected function getSystemMailer()
    {
        $this->getMock('SystemMailer', array('send');
    }   
    protected function getRouter()
    {
        $this->getMock('RouterInterface', array('generate');
    }

    protected function getTemplatingEngine()
    {
        $this->getMock('RouterInterface', array('render');
    }
}

Проблема в том, что мои фиктивные объекты не реализуют Symfony \ Bundle \ FrameworkBundle \ Templating \ EngineInterface и Symfony \ Component \ Routing \ RouterInterface, поэтому я не могу использовать фиктивные объекты, которые я создаю сам. Один из методов, который я попробовал, - это создание абстрактного класса, который реализует правильный интерфейс на тестовой странице, однако getMockForAbstractClass завершается ошибкой, заявляя, что не может найти класс ...

1 Ответ

7 голосов
/ 16 ноября 2011

При имитации вам нужно использовать полный путь к классу , так как при имитации функциональность не учитывает пространство имен вызывающего кода или любые операторы "использования".

Попробуйте

->getMock('\\Symfony\\Component\\Routing\\RouterInterface'); 

и пропустите второй параметр.Обычно указание методов намного хуже, чем пользы.Только если вы хотите , чтобы все остальные методы работали так же, как раньше, вам нужен второй параметр.

Пример

<?php

namespace bar;

class MyClass {}

namespace foo;

use \bar\MyClass;

class MockingTest extends \PHPUnit_Framework_TestCase {

    public function testMock() {
        var_dump($this->getMock('MyClass') instanceOf MyClass);
        var_dump($this->getMock('\\bar\\MyClass') instanceOf MyClass);
    }   
}

Производит:

/phpunit.sh --debug fiddleTestThree.php 
PHPUnit @package_version@ by Sebastian Bergmann.


Starting test 'foo\MockingTest::testMock'.
.bool(false)
bool(true)
...