yvoyer
yvoyer

Reputation: 7516

Symfony2: How to test Configuration nodes values and index

In Symfony2, using this class setup, how can I test that each nodes is defined in the Configuration class, and that their values are correctly configured.

The class to test

# My\Bundle\DependencyInjection\Configuration.php

class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $treeBuilder->root('my_bundle')
            ->children()
                ->scalarNode("scalar")->defaultValue("defaultValue")->end()
                ->arrayNode("arrayNode")
                    ->children()
                        ->scalarNode("val1")->defaultValue("defaultValue1")->end()
                        ->scalarNode("val2")->defaultValue("defaultValue2")->end()
                    ->end()
                ->end()
            ->end()
        ;

        return $treeBuilder;
    }
}

Here are the assertions I would like to do, in my unit test:

I tried to access the nodes as an array, but it do not seems to work. Also the TreeBuilder do not seems to give us the possibility of getting the configurations as a array, unless they are loaded by the bundle extension.

Tests

# My\Bundle\Tests\DependencyInjection\ConfigurationTest.php

$configuration = $this->getConfiguration();
$treeBuilder   = $configuration->getConfigTreeBuilder();

$this->assertInstanceOf("Symfony\Component\Config\Definition\Builder\TreeBuilder", $treeBuilder);

// How to access the treebuilder's nodes ?
$rootNode   = $treeBuilder["my_bundle"];
$scalarNode = $treeBuilder["scalar"];
$arrayNode  = $treeBuilder["arrayNode"];
$val1Node   = $arrayNode["val1"];
$val2Node   = $arrayNode["val2"];

$this->assertInstanceOf("Symfony\...\ArrayNodeDefinition", $rootNode);
$this->assertEquals("defaultValue", $scalarNode, "Test the default value of the node");
$this->assertEquals("defaultValue", $val1Node, "Test the default value of the node");
$this->assertEquals("defaultValue", $val2Node, "Test the default value of the node");

Upvotes: 8

Views: 3705

Answers (2)

Cethy
Cethy

Reputation: 1636

To test your configuration in isolation, you can do this :

use Foo\YourBundle\DependencyInjection\Configuration;
use PHPUnit\Framework\TestCase;

class ConfigurationTest extends TestCase
{
    /**
     * @dataProvider dataTestConfiguration
     *
     * @param mixed $inputConfig
     * @param mixed $expectedConfig
     */
    public function testConfiguration($inputConfig, $expectedConfig)
    {
        $configuration = new Configuration();

        $node = $configuration->getConfigTreeBuilder()
            ->buildTree();
        $normalizedConfig = $node->normalize($inputConfig);
        $finalizedConfig = $node->finalize($normalizedConfig);

        $this->assertEquals($expectedConfig, $finalizedConfig);
    }

    public function dataTestConfiguration()
    {
        return [
            'test configuration'   => [
                ['input'],
                ['expected_config']
            ],
            // ...
        ];
    }
}

Upvotes: 4

yvoyer
yvoyer

Reputation: 7516

I found out a solution that could work based on JMSSecurityBundle.

Instead of testing the configuration, I test the extension which will add coverage for the configuration by the way. That way, I can assert that a default configuration was set.

For instance, this Extension.

#My\Bundle\DependencyInjection\MyBundleExtension
class MyBundleExtension extends Extension
{
    /**
     * {@inheritDoc}
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $configuration = new Configuration();
        $config        = $this->processConfiguration($configuration, $configs);

        $container->setParameter("crak_landing_frontend.scalar", $config["scalar"]);
        $container->setParameter("crak_landing_frontend.array_node", $config["array_node"]);

        $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('services.xml');
    }
}

Could be tests like:

#My\Bundle\Tests\DependencyInjection\MyBundleExtensionTest
class MyBundleExtensionTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @var MyBundleExtension
     */
    private $extension;

    /**
     * Root name of the configuration
     *
     * @var string
     */
    private $root;

    public function setUp()
    {
        parent::setUp();

        $this->extension = $this->getExtension();
        $this->root      = "my_bundle";
    }

    public function testGetConfigWithDefaultValues()
    {
        $this->extension->load(array(), $container = $this->getContainer());

        $this->assertTrue($container->hasParameter($this->root . ".scalar"));
        $this->assertEquals("defaultValue", $container->getParameter($this->root . ".scalar"));

        $expected = array(
            "val1" => "defaultValue1",
            "val2" => "defaultValue2",
        );
        $this->assertTrue($container->hasParameter($this->root . ".array_node"));
        $this->assertEquals($expected, $container->getParameter($this->root . ".array_node"));
    }

    public function testGetConfigWithOverrideValues()
    {
        $configs = array(
            "scalar"     => "scalarValue",
            "array_node" => array(
                "val1" => "array_value_1",
                "val2" => "array_value_2",
            ),
        );

        $this->extension->load(array($configs), $container = $this->getContainer());

        $this->assertTrue($container->hasParameter($this->root . ".scalar"));
        $this->assertEquals("scalarValue", $container->getParameter($this->root . ".scalar"));

        $expected = array(
            "val1" => "array_value_1",
            "val2" => "array_value_2",
        );
        $this->assertTrue($container->hasParameter($this->root . ".array_node"));
        $this->assertEquals($expected, $container->getParameter($this->root . ".array_node"));
    }

    /**
     * @return MyBundleExtension
     */
    protected function getExtension()
    {
        return new MyBundleExtension();
    }

    /**
     * @return ContainerBuilder
     */
    private function getContainer()
    {
        $container = new ContainerBuilder();

        return $container;
    }
}

Upvotes: 11

Related Questions