Модульное тестирование Dependency Injection в Symfony2

Кофигурация проекта является довольно критичным функционалом, который, однако, часто забывают тестировать. В Symfony2 используется система сервисов, реализующая паттерн dependency injection. И правильную обработку параметров и передачу их в контейнер необходимо тестировать так же, как и любой другой код.

Для примера я возьму свой последний проект - HTML5CacheBundle.

Бандл реализует возможность использовать HTML5 Application Cache в проекте на Symfony2, для этого нужно указать пути к статическим файлам, которые нужно кешировать. Учтена возможность работы с локальным CDN (в т.ч. SSL). Также можно указать сторонние библиотеки, такие как jQuery или Twitter Bootstrap.

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

#HTML5CacheBundl
html5_cache:
    cdn: cdn.site.com
    http: true
    https: false
    custom_urls:
        - https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js
        - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css
        - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css
        - https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js
        - ...

Для использования конфигураций в системе необходимо создать каталог DependencyInjection и разместить в нем файл Configuration, который содержит дерево конфигурации, и HTML5CacheExtension, который добавляет в контейнер наши параметры.

Приведу основные моменты в вышеуказанных файлах.

Configuration:

/**
  * Class Configuration
  * @package Evheniy\HTML5CacheBundle\DependencyInjection
  */
class Configuration implements ConfigurationInterface
{
     /**
     * @return TreeBuilder
     */
     public function getConfigTreeBuilder()
     {
         $treeBuilder = new TreeBuilder();
         $rootNode = $treeBuilder->root('html5_cache');
         $rootNode
             ->children()
                 ->scalarNode('cdn')->defaultValue('')->end()
                 ->booleanNode('http')->defaultTrue()->end()
                 ->booleanNode('https')->defaultTrue()->end()
                 ->arrayNode('custom_paths')->prototype('scalar')->end()
             ->end()
         ->end();
         return $treeBuilder;
     }
}

HTML5CacheExtension:

/**
  * Class HTML5CacheBundle
  *
  * @package Evheniy\HTML5CacheBundle\DependencyInjection
  */
class HTML5CacheExtension extends Extension
{
     /**
     * @param array            $configs
     * @param ContainerBuilder $container
     */
     public function load(array $configs, ContainerBuilder $container)
     {
         $processor = new Processor();
         $configuration = new Configuration();
         $config = $processor->processConfiguration($configuration, $configs);
         $container->setParameter('html5_cache', $config);
...
    

Как видно в первом файле я описал дерево возможных комбинаций параметров, а второй файл (само расширение) получает параметры из контейнера и обрабатывает их с учетом нашего дерева.

Осталось протестировать полученный код. В бандле в директории Tests нужно создать одноименную папку DependencyInjection, в которой будет распологаться наш файл тестов HTML5CacheExtensionTest.

Для тестирования я выбрал бандл с небольшим набором параметров, в котром большая часть параметров имеет значения по умолчанию. Поэтому тестирование сводится к проверке параметров по умолчанию и проверке установленных параметров.

Для тестирования параметров по умолчанию достаточно загрузить расширение без указанных параметров:

protected function setUp()
{
     $this->extension = new HTML5CacheExtension();
     $this->container = new ContainerBuilder();
     $this->container->registerExtension($this->extension);
}
 
public function testWithoutConfiguration()
{
     $this->container->loadFromExtension($this->extension->getAlias());
     $this->container->compile();
     $this->assertTrue($this->container->hasParameter('html5_cache'));
     $html5Cache = $this->container->getParameter('html5_cache');
     $this->assertEmpty($html5Cache['cdn']);
     $this->assertTrue($html5Cache['http']);
     $this->assertTrue($html5Cache['https']);
}

Здесь я проверяю наличие 3 параметров и их значения.

Для тестирования параметров я создал файл Fixtures/test.yml:

html5_cache:
    cdn: //cdn.site.com
    http: false
    https: false
    

Этот файл необходимо загрузить и проверить значения

/**
  * @param ContainerBuilder $container
  * @param string           $resource
  */
protected function loadConfiguration(ContainerBuilder $container, $resource)
{
     $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/Fixtures/'));
     $loader->load($resource . '.yml');
}
 
/**
  * Test normal config
  */
public function testTest()
{
     $this->loadConfiguration($this->container, 'test');
     $this->container->compile();
     $this->assertTrue($this->container->hasParameter('html5_cache'));
     $html5Cache = $this->container->getParameter('html5_cache');
     $this->assertNotEmpty($html5Cache['cdn']);
     $this->assertEquals($html5Cache['cdn'], 'cdn.site.com');
     $this->assertEmpty($html5Cache['https']);
     $this->assertFalse($html5Cache['https']);
     $this->assertEmpty($html5Cache['http']);
     $this->assertFalse($html5Cache['http']);
}

Для 100% покрытия кода можно проверить имя расширения:

public function testGetAlias()
{
     $this->assertEquals($this->extension->getAlias(), 'html5_cache');
}

Как видим нет ничего сложного, чтоб выпускать код более высокого качества и стремиться к максимальному покрытию кода тестами.

Теги: Dependency, Injection, Symfony2, Phpunit, Di


Похожие статьи

Модульное тестирование (phpunit)

PHP Depend