Weave 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
Bundle Tests
symkit/search-bundle
cursor
phpunit
symfony
test-kernel
live-components
twig-components
mutation-testing
bundle-testing

Testing patterns for Symfony bundle test suites

Install
php artisan boost:add-skill symkit/search-bundle

Save this content to: .cursor/rules/bundle-tests.mdc

# Bundle Test Conventions

## General

- `declare(strict_types=1)` in test files too
- Structure: `tests/Unit/`, `tests/Integration/`, `tests/Functional/` when applicable; for small bundles a lighter layout is fine (e.g. only `tests/Integration/`)
- PHPUnit testsuite name in `phpunit.xml.dist` can stay generic (e.g. "Unit") even if test classes live under `Integration/`
- Use `nyholm/symfony-bundle-test` with `TestKernel` for integration tests

## Minimum Required Tests

- Bundle boots without error
- All services are correctly registered and wired
- Configuration validation (required keys, default values, custom values)
- Twig prepend (paths registered, globals set) when applicable

## Exception Handler Cleanup

Symfony's TestKernel registers exception handlers. Always restore them in `tearDown()` to avoid PHPUnit "risky test" warnings:

```php
protected function tearDown(): void
{
    parent::tearDown();
    \restore_exception_handler();
}
```

## Integration Test Template

```php
use Nyholm\BundleTest\TestKernel;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpKernel\KernelInterface;

final class BundleBootTest extends KernelTestCase
{
    protected function tearDown(): void
    {
        parent::tearDown();
        \restore_exception_handler();
    }

    protected static function getKernelClass(): string
    {
        return TestKernel::class;
    }

protected static function createKernel(array $options = []): KernelInterface
    {
        /** @var TestKernel $kernel */
        $kernel = parent::createKernel($options);
        $kernel->addTestBundle(VendorNameBundle::class);
        $kernel->addTestConfig(static function ($container): void {
            $container->loadFromExtension('framework', ['test' => true]);
        });
        $kernel->handleOptions($options);

        return $kernel;
    }
}
```

Key patterns:
- `/** @var TestKernel $kernel */` for PHPStan compatibility
- `static function` closures in `addTestConfig()` (no `$this` binding)
- Register TwigBundle when testing Twig integration (globals, paths)
- `$kernel->getContainer()->get('test.service_container')->get('twig')` for Twig access in custom-booted kernels

## PHPUnit Configuration

- `failOnRisky="true"` in `phpunit.xml.dist` (enforce clean tests)
- Always pair with `restore_exception_handler()` in `tearDown()` to pass risky check

## Live Components

Test with `InteractsWithLiveComponents` trait in `KernelTestCase`:

```php
use Symfony\UX\LiveComponent\Test\InteractsWithLiveComponents;

$component = $this->createLiveComponent(name: SearchLive::class, data: ['query' => 'test']);
$component->call('loadMore');
self::assertSame(2, $component->component()->page);
```

## Twig Components

Test rendering via Twig render assertions or by checking rendered HTML output.

## After Every Change

Run `make test` then `make infection` to verify coverage and mutation score.

Bundle Test Conventions

General

  • declare(strict_types=1) in test files too
  • Structure: tests/Unit/, tests/Integration/, tests/Functional/ when applicable; for small bundles a lighter layout is fine (e.g. only tests/Integration/)
  • PHPUnit testsuite name in phpunit.xml.dist can stay generic (e.g. "Unit") even if test classes live under Integration/
  • Use nyholm/symfony-bundle-test with TestKernel for integration tests

Minimum Required Tests

  • Bundle boots without error
  • All services are correctly registered and wired
  • Configuration validation (required keys, default values, custom values)
  • Twig prepend (paths registered, globals set) when applicable

Exception Handler Cleanup

Symfony's TestKernel registers exception handlers. Always restore them in tearDown() to avoid PHPUnit "risky test" warnings:

protected function tearDown(): void
{
    parent::tearDown();
    \restore_exception_handler();
}

Integration Test Template

use Nyholm\BundleTest\TestKernel;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpKernel\KernelInterface;

final class BundleBootTest extends KernelTestCase
{
    protected function tearDown(): void
    {
        parent::tearDown();
        \restore_exception_handler();
    }

    protected static function getKernelClass(): string
    {
        return TestKernel::class;
    }

protected static function createKernel(array $options = []): KernelInterface
    {
        /** @var TestKernel $kernel */
        $kernel = parent::createKernel($options);
        $kernel->addTestBundle(VendorNameBundle::class);
        $kernel->addTestConfig(static function ($container): void {
            $container->loadFromExtension('framework', ['test' => true]);
        });
        $kernel->handleOptions($options);

        return $kernel;
    }
}

Key patterns:

  • /** @var TestKernel $kernel */ for PHPStan compatibility
  • static function closures in addTestConfig() (no $this binding)
  • Register TwigBundle when testing Twig integration (globals, paths)
  • $kernel->getContainer()->get('test.service_container')->get('twig') for Twig access in custom-booted kernels

PHPUnit Configuration

  • failOnRisky="true" in phpunit.xml.dist (enforce clean tests)
  • Always pair with restore_exception_handler() in tearDown() to pass risky check

Live Components

Test with InteractsWithLiveComponents trait in KernelTestCase:

use Symfony\UX\LiveComponent\Test\InteractsWithLiveComponents;

$component = $this->createLiveComponent(name: SearchLive::class, data: ['query' => 'test']);
$component->call('loadMore');
self::assertSame(2, $component->component()->page);

Twig Components

Test rendering via Twig render assertions or by checking rendered HTML output.

After Every Change

Run make test then make infection to verify coverage and mutation score.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin