Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Symfony Config Test Laravel Package

matthiasnoback/symfony-config-test

PHPUnit helpers for testing Symfony Config definitions. Provides a test case trait and assertions to validate config trees, ensuring required nodes, types, and constraints behave as expected by asserting valid and invalid configuration arrays.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

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

    Add to your composer.json under require-dev to ensure it’s only installed for testing.

  2. Basic Test Structure: Create a test class extending PHPUnit\Framework\TestCase and include the trait:

    use Matthias\SymfonyConfigTest\PhpUnit\ConfigurationTestCaseTrait;
    
    class MyConfigTest extends TestCase
    {
        use ConfigurationTestCaseTrait;
    
        protected function getConfiguration(): ConfigurationInterface
        {
            return new MyAppConfiguration(); // Your Symfony Config Component class
        }
    }
    
  3. First Use Case: Test invalid configuration with missing required values:

    public function test_missing_required_value()
    {
        $this->assertConfigurationIsInvalid([[]], 'required_value');
    }
    

Implementation Patterns

Workflow Integration

  1. Testing Configuration Validation:

    • Use assertConfigurationIsInvalid() for invalid inputs (e.g., missing required fields, wrong types).
    • Example:
      public function test_invalid_type()
      {
          $this->assertConfigurationIsInvalid(
              [['invalid_key' => 123]], // Wrong type (should be string)
              'Expected a string'
          );
      }
      
  2. Testing Processed Configuration:

    • Use assertProcessedConfigurationEquals() to verify merged/processed config matches expectations.
    • Example:
      public function test_processed_config()
      {
          $this->assertProcessedConfigurationEquals(
              [
                  ['app' => ['debug' => true]],
                  ['app' => ['debug' => false]]
              ],
              ['app' => ['debug' => false]] // Final merged state
          );
      }
      
  3. Partial Tree Testing:

    • Isolate tests for specific branches using $breadcrumbPath (e.g., doctrine.orm).
    • Example:
      public function test_doctrine_orm_only()
      {
          $this->assertProcessedConfigurationEquals(
              [['doctrine' => ['orm' => ['entities' => ['App\Entity\User']]]]],
              ['doctrine' => ['orm' => ['entities' => ['App\Entity\User']]]],
              'doctrine.orm'
          );
      }
      
  4. Prototyped Nodes:

    • Test prototyped arrays (e.g., array_node.*) with wildcards:
      public function test_prototyped_defaults()
      {
          $this->assertProcessedConfigurationEquals(
              [['services' => ['*' => ['autowire' => true]]]],
              ['services' => ['default' => ['autowire' => true]]],
              'services.*.autowire'
          );
      }
      

Laravel-Specific Patterns

  1. Bundle Configuration:

    • Test Laravel package configs (e.g., config/your-package.php) by mocking the config loader or using the package’s Configuration class directly.
    • Example:
      protected function getConfiguration(): ConfigurationInterface
      {
          return new YourPackageConfiguration();
      }
      
  2. Environment-Aware Tests:

    • Use assertConfigurationIsInvalid() to validate .env or config file inputs:
      public function test_env_validation()
      {
          $this->assertConfigurationIsInvalid(
              [['APP_DEBUG' => 'invalid']],
              'must be a boolean'
          );
      }
      
  3. Service Provider Integration:

    • Test config processed by service providers (e.g., register() methods) by injecting the config class into the test:
      public function test_service_provider_config()
      {
          $provider = new YourServiceProvider(app());
          $config = $provider->getConfig(); // Hypothetical method
          $this->assertProcessedConfigurationEquals([...], $config);
      }
      

Gotchas and Tips

Common Pitfalls

  1. Breadcrumb Path Syntax:

    • Mistake: Using array_node/child (slashes) instead of array_node.child (dots).
    • Fix: Always use dots for nested paths (e.g., database.connections.mysql).
    • Prototypes: Use * for prototyped nodes (e.g., services.*.autowire).
  2. Merging Logic:

    • Mistake: Forgetting that assertProcessedConfigurationEquals() expects an array of arrays to simulate merging.
    • Fix: Always pass nested arrays, even for single configs:
      // Correct:
      $this->assertProcessedConfigurationEquals([['key' => 'value']], ['key' => 'value']);
      
  3. Partial Testing Quirks:

    • Mistake: Testing a partial path (doctrine.orm) but providing config for unrelated branches (e.g., doctrine.dbal).
    • Fix: Ensure input arrays only include paths under the tested branch.
  4. Exception Messages:

    • Mistake: Relying on exact exception messages (Symfony’s messages may change).
    • Fix: Use partial matches or regex in assertConfigurationIsInvalid():
      $this->assertConfigurationIsInvalid([[]], '/required.*value/');
      

Debugging Tips

  1. Inspect Processed Config:

    • Use Symfony’s ConfigCache or Processor directly to debug:
      $processor = new Processor();
      $processed = $processor->processConfiguration(
          $this->getConfiguration(),
          [['raw' => 'input']]
      );
      dd($processed); // Debug output
      
  2. PHPUnit Debugging:

    • Enable verbose assertions:
      $this->assertProcessedConfigurationEquals([...], [...], null, true); // Verbose mode
      
  3. CI/CD Integration:

    • Tip: Run tests in CI with --debug to catch flaky assertions:
      phpunit --debug
      

Extension Points

  1. Custom Assertions:

    • Extend the trait to add domain-specific assertions:
      trait CustomConfigTestTrait
      {
          protected function assertCustomConfig(array $input, array $expected)
          {
              $this->assertProcessedConfigurationEquals([$input], $expected);
              // Add custom logic (e.g., validate against a schema)
          }
      }
      
  2. Integration with Laravel’s Config:

    • Override getConfiguration() to load Laravel’s config:
      protected function getConfiguration(): ConfigurationInterface
      {
          return new class extends Configuration {
              public function getConfigTreeBuilder()
              {
                  return (new TreeBuilder())
                      ->root('app')
                      ->children()
                          ->scalarNode('timezone')->defaultValue(config('app.timezone'))->end()
                      ->end();
              }
          };
      }
      
  3. Mocking Dependencies:

    • Mock external services (e.g., database) in config tests:
      public function test_database_config()
      {
          $this->mockDatabaseConnection();
          $this->assertProcessedConfigurationEquals([...], [...], 'database');
      }
      

Performance

  • Tip: Cache processed configs in tests to avoid reprocessing:
    private $processedConfigCache = [];
    
    protected function getProcessedConfig(array $input)
    {
        $cacheKey = md5(serialize($input));
        return $this->processedConfigCache[$cacheKey] ?? (
            $this->processedConfigCache[$cacheKey] = $this->processConfig($input)
        );
    }
    

Laravel-Specific Gotchas

  1. Config Publishing:

    • Ensure published configs (e.g., php artisan vendor:publish) are tested:
      public function test_published_config()
      {
          $this->publishConfig();
          $this->assertProcessedConfigurationEquals([...], config('published-key'));
      }
      
  2. Environment Variables:

    • Test .env overrides by mocking env():
      protected function setUp(): void
      {
          $this->mockEnv(['APP_DEBUG' => 'true']);
      }
      
  3. Package Configs:

    • For packages with dynamic configs (e.g., config/your-package.php), ensure tests reflect all possible states:
      public function test_all_package_config_states()
      {
          $this->assertProcessedConfigurationEquals([...], [...], 'your-package');
          $this->assertProcessedConfigurationEquals([...], [...], 'your-package.other-section');
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/privacy-filter-classifier
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi