matthiasnoback/symfony-config-test

用于测试与Symfony Config组件相关的用户类的库

v5.2.0 2024-06-23 19:12 UTC

README

由Matthias Noback及贡献者编写

Build Status

使用Symfony Config组件定义配置类可能会很困难。为了帮助您验证生成的配置节点树的有效性,此库提供了一个PHPUnit测试用例和一些自定义断言。

安装

使用Composer

composer require --dev matthiasnoback/symfony-config-test

用法

创建一个测试用例,并使用来自Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait的特质。然后实现getConfiguration()

<?php

use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait;
use PHPUnit\Framework\TestCase;
use App\Configuration;

class ConfigurationTest extends TestCase
{
    use ConfigurationTestCaseTrait;

    protected function getConfiguration(): Configuration
    {
        return new Configuration();
    }
}

测试无效的配置值

假设您想测试的Configuration类看起来像这样

<?php

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class ConfigurationWithRequiredValue implements ConfigurationInterface
{
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder();

        $rootNode = $treeBuilder->root('root');
        $rootNode
            ->isRequired()
            ->children()
                ->scalarNode('required_value')
                    ->isRequired()
                ->end()
            ->end();

        return $treeBuilder;
    }
}

当你为这个配置提供一个空数组作为值时,你会期望抛出一个异常,因为required_value节点是必需的。你可以使用assertConfigurationIsInvalid()方法断言一组配置值是无效的

<?php

use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait;
use PHPUnit\Framework\TestCase;

class ConfigurationTest extends TestCase
{
    use ConfigurationTestCaseTrait;

    /**
     * @test
     */
    public function values_are_invalid_if_required_value_is_not_provided(): void
    {
        $this->assertConfigurationIsInvalid(
            [
                [] // no values at all
            ],
            'required_value' // (part of) the expected exception message - optional
        );
    }
}

测试处理后的配置值

你可能还想要验证处理配置值数组后的结果是否符合预期

<?php

use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait;
use PHPUnit\Framework\TestCase;

class ConfigurationTest extends TestCase
{
    use ConfigurationTestCaseTrait;

    /**
     * @test
     */
    public function processed_value_contains_required_value(): void
    {
        $this->assertProcessedConfigurationEquals([
            ['required_value' => 'first value'],
            ['required_value' => 'last value']
        ], [
            'required_value'=> 'last value'
        ]);
    }
}

请注意:每个assert*方法的第一个参数都是一个数组数组。额外的嵌套级别允许你测试合并过程。请参阅配置组件文档的合并选项部分。

测试配置树的一个子集

使用这个库可以测试配置树的一个分支。考虑以下节点树定义,它包含分支array_node_1array_node_2

<?php

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class ConfigurationWithTwoBranches implements ConfigurationInterface
{
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder();

        $rootNode = $treeBuilder->root('root');
        $rootNode
            ->children()
                ->arrayNode('array_node_1')
                    ->isRequired()
                    ->children()
                        ->scalarNode('required_value_1')
                            ->isRequired()
                        ->end()
                    ->end()
                ->end()
                ->arrayNode('array_node_2')
                    ->isRequired()
                    ->children()
                        ->scalarNode('required_value_2')
                            ->isRequired()
                        ->end()
                    ->end()
                ->end()
            ->end();

        return $treeBuilder;
    }
}

如果你只想测试下面的示例中的array_node_1分支,并忽略array_node_2,请为测试辅助函数的$breadcrumbPath参数提供array_node_1,例如

/**
 * @test
 */
public function processed_configuration_for_array_node_1(): void
{
    $this->assertProcessedConfigurationEquals(
        [
            ['array_node_1' => ['required_value_1' => 'original value']],
            ['array_node_1' => ['required_value_1' => 'final value']]
        ],
        [
            'array_node_1' => [
                'required_value_1' => 'final value'
            ]
        ],
        // the path of the nodes you want to focus on in this test:
        'array_node_1'
    );
}

这将触发array_node_2分支中任何值的验证错误。

请注意,$breadcrumbPath可以更具体,例如"doctrine.orm"(这将跳过分支"doctrine.dbal"等的配置处理)。

请注意,你只能使用点.在面包屑路径中遍历数组节点。面包屑路径的最后部分可以是任何其他类型的节点。

测试原型配置树的一个子集

你可以使用面包屑路径中的*作为其名称来遍历原型数组节点。

<?php

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

class PrototypedConfiguration implements ConfigurationInterface
{
    public function getConfigTreeBuilder(): TreeBuilder
    {
        $treeBuilder = new TreeBuilder();

        $rootNode = $treeBuilder->root('root');
        $rootNode
            ->children()
                ->arrayNode('array_node')
                    ->useAttributeAsKey('name')
                    ->prototype('array')
                        ->children()
                            ->scalarNode('default_value')->cannotBeEmpty()->defaultValue('foobar')->end()
                            ->scalarNode('required_value')->isRequired()->end()
                        ->end()
                    ->end()
                ->end()
            ->end();

        return $treeBuilder;
    }
}

如果你想测试默认情况下default_value是否设置为foobar,但不想测试受到required_value节点要求的约束,你可以定义其路径为array_node.*.default_value,例如

/**
 * @test
 */
public function processed_configuration_for_array_node_1(): void
{
    $this->assertProcessedConfigurationEquals(
        [
            ['array_node' => ['prototype_name' => null]],
        ],
        [
            'array_node' => [
                'prototype_name' => [
                    'default_value' => 'foobar'
                ]
            ]
        ],
        // the path of the nodes you want to focus on in this test:
        'array_node.*.default_value'
    );
}

版本指导