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

Symfony Bundle Testing Laravel Package

mekras/symfony-bundle-testing

Testing utilities for Symfony bundles: helpers for booting test kernels, configuring services, and writing functional and integration tests around your bundle code. Simplifies PHPUnit setup so you can focus on assertions.

View on GitHub
Deep Wiki
Context7

Getting Started

This package gives you a fluent way to compile a Symfony service container in tests and assert on its wiring. Day-to-day, you'll use it to prove that your bundle/extension config actually produces the services you expect — without booting a full kernel.

Minimal steps:

  1. Require the package as a require-dev dependency.
  2. Extend BaseSymfonyIntegrationTestCase (or whichever base test case your suite already uses) in your integration test.
  3. Look first at TestContainerBuilder — it is the new entry point for everything: extensions, bundles, locatability, visibility, and assertions.
  4. Write your first test around the most common question you have: "does this config produce my service?"
use Acme\Testing\BaseSymfonyIntegrationTestCase;

final class ServiceWiringTest extends BaseSymfonyIntegrationTestCase
{
    public function test_service_is_registered(): void
    {
        $this->createContainerFromFile(__DIR__.'/Fixtures/services.yaml')
            ->expectDefinitionsExists(MyService::class);
    }
}

The first real use case is almost always a regression guard: you changed an extension's load() method or a bundle's services.yaml, and you want a test that fails loudly when a definition disappears or stops being public.

Implementation Patterns

Build once per test, assert fluently. createContainer() / createContainerFromFile() now return a TestContainerBuilder, so the natural style is a single chain:

$builder = $this->createContainerFromFile(__DIR__.'/Fixtures/config.yaml');

$builder
    ->registerBundle(AcmeBundle::class)
    ->loadExtension('acme', ['api_key' => 'test', 'debug' => true])
    ->makePublic()
    ->expectDefinitionsExists(Acme\Client::class);

Configuration-matrix testing. Put config arrays in a data provider and build a fresh container per case. The builder is cheap enough to create per test, and isolating it avoids leaking compiled state between cases.

Locator-based retrieval for behaviour tests. When you want to call the service rather than just assert it exists, mark it locatable and pull it out:

$service = $this->createContainerFromFile(__DIR__.'/Fixtures/config.yaml')
    ->loadExtension('acme', ['transport' => 'null'])
    ->makeLocatable(Acme\Mailer::class)
    ->locate(Acme\Mailer::class);

self::assertInstanceOf(Acme\Mailer::class, $service);

Migrate legacy tests incrementally. Every deprecated base-class method has a builder equivalent, so old tests can be rewritten mechanically without changing what they assert:

Deprecated on BaseSymfonyIntegrationTestCase Replacement on TestContainerBuilder
loadExtension() loadExtension()
registerBundle() registerBundle()
expectServiceExists() expectDefinitionsExists()
addToLocator() makeLocatable()
getFromLocator() locate()
createContainer(..., $public: true) createContainer(...)->makePublic()

Integration tip: treat the builder as the seam for your own helpers. A small makeContainer(array $config = []) factory in a base test case keeps the fluent chain out of individual tests and gives you one place to update when the API moves again.

Extension points: loadExtension() is the hook for exercising your Extension::load()/prepend() logic in isolation, and registerBundle() lets you verify bundle-level prepend() behaviour without a kernel. These two cover most of the value in a bundle's test suite.

Gotchas and Tips

  • Return type change is the real breaking change. createContainer() and createContainerFromFile() now return TestContainerBuilder, not a container. Any test doing $this->createContainer()->get(Foo::class) will break. Replace with ->locate(Foo::class) (after makeLocatable()) or assert via expectDefinitionsExists() instead of resolving.
  • $public argument is deprecated, not removed. createContainer(public: true) still works today but emits deprecations. Switch to ->makePublic() now, while the test suite is already green, rather than during a later upgrade.
  • expectServiceExists() → expectDefinitionsExists() is a rename with a nuance. The new name says definitions, which is what you're actually asserting. Aliases, synthetic services, and services produced by factories may not show up the way a "service exists" assertion implied — check those cases explicitly.
  • Order matters in the chain. Register bundles and load extensions before you assert or locate; makePublic()/makeLocatable() must come after the definition exists. If a lookup returns nothing, check the ordering before assuming a wiring bug.
  • Locator retrieval needs both halves. locate() only works for services you've passed through makeLocatable(). A missing entry is usually a forgotten makeLocatable(), not a broken container.
  • Debugging failures: when an assertion fails, dump the compiled container ($builder->locate('service_container') or the kernel's debug:container equivalent) and diff against expectations. Definition IDs, not class names, are the usual source of surprise.
  • Deprecations are your migration checklist. Run the suite with deprecation reporting enabled after upgrading to 0.3.0 — the package will tell you exactly which legacy calls you still have.
  • Keep the builder out of production paths. Everything here is test-only; don't be tempted to reuse TestContainerBuilder for container introspection in application code.
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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums