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

Service Mocking Laravel Package

happyr/service-mocking

HappyR Service Mocking is a Laravel testing helper that makes it easy to replace real services with mocks in the container. Swap bindings during functional and integration tests to isolate dependencies and control behavior without manual container wiring or boilerplate.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. happyr/service-mocking is a Symfony bundle plus a ServiceMockTrait that swaps real service definitions inside a compiled DI container for PHPUnit/Mockery doubles, targeting KernelTestCase. Laravel has no compile step and no test container of its own; it binds at runtime through Illuminate\Container\Container and service providers. Laravel's native $this->mock(), $this->partialMock(), $this->spy(), and $this->instance() already cover the bulk of "mock a service inside the built container." As a literal dependency for a Laravel app, the architecture fit is poor; as a pattern reference for container-level mocking it is decent.

Integration feasibility. Low as a drop-in. The package requires symfony/dependency-injection, symfony/framework-bundle, and a Symfony kernel test base class. Those libraries coexist in a Laravel vendor tree (Laravel already ships Symfony components), but the bundle is not auto-registered by Laravel's provider system and the trait targets the wrong base test case. A wrapper that maps getMockedService() semantics onto app()->instance() / bind() is feasible in roughly one to three engineer-days — but at that point the team is reimplementing a small concept, not integrating a package. With 45 stars and zero dependents, there is no documented Laravel usage path; the team would be the first.

Technical risk. Medium, and confined to CI since this is a require-dev package. The dominant risk is version lock-step: Symfony 5–7 support must track Laravel's pinned Symfony components (Laravel 11 → Symfony 7, Laravel 10 → 6.4), and the two will not upgrade on the same cadence. Container manipulation also has sharp edges — private services, aliases, decorated services, final classes, readonly promoted properties — that Laravel-only engineers have no intuition for. Maintenance is single-vendor (a Swedish consultancy), though the 2024-10-08 release is a positive signal that it is not abandoned.

Key questions.

  • Is any surface of the estate actually Symfony — a legacy service, shared library, or monorepo package? If yes, the package has a legitimate home there, not in the Laravel app.
  • What specifically fails with Laravel's native $this->mock() / $this->instance()? Is the pain "mock a service constructed deep inside a provider" or "mock at container-compile time"? Only the latter justifies anything resembling this package.
  • What is the current split between Laravel feature tests and plain unit tests with hand-rolled doubles?
  • Who owns test infrastructure long-term, and does a 45-star, single-vendor dependency clear the OSS policy bar?
  • Does the team need parity with a partner team's Symfony test suite that already uses compiled-container mocking?

Integration Approach

Stack fit. Target is PHP 8.1+ / Laravel 10–11. The package's public API is a trait plus a bundle; neither has an Illuminate counterpart. For a Laravel-only codebase the practical fit is "inspiration, not dependency." Standardize instead on $this->mock(Contract::class, ...), $this->instance(), $this->spy(), and container bind() overrides in a shared test case. That covers roughly 90% of the described capability with zero new dependencies. If compile-time-style mocking is genuinely required, build a small internal MockableServiceRegistry that records intended bindings before bootstrap() and applies them in register()/boot() — the Laravel-idiomatic rendering of this package's idea.

Migration path. Do not introduce the Symfony bundle into the Laravel app. Port the concept: a MockableServices test trait that resolves configured service IDs from app(), rebinds them to Mockery doubles in setUp(), and restores originals via app()->forgetInstance() in tearDown(). If a genuine Symfony service exists in the estate (queue worker, CLI tool, extracted microservice), pilot the real package there first — composer require --dev happyr/service-mocking, register the bundle only in the test environment, and use ServiceMockTrait in KernelTestCase subclasses. Prove the pattern on the Symfony side, then decide whether Laravel parity is worth the port.

Compatibility. Pin the package's Symfony major support and verify against Laravel's transitive Symfony components explicitly; expect friction at every Symfony major bump. Mockery/PHPUnit alignment is the likelier break — validate the trait's mocking contract against the PHPUnit major in use. There is no facade, no package discovery, and nothing lands in config/.

Sequencing.

  1. Inventory current mocking pain: which tests would need this, and what do they do today?
  2. Prototype with Laravel-native helpers only — one sprint or less.
  3. If gaps remain, write the internal adapter (~1–3 days) rather than adding the dependency.
  4. Only where a real Symfony surface exists, pilot the actual package.
  5. Record the outcome in an ADR: "container-time mocking is handled by X; this package is not a Laravel dependency."

Operational Impact

Maintenance. Adopting it in a Laravel app means owning an unsupported integration. The package is small (a compiler pass plus a trait), so vendoring or forking is cheap if the maintainer goes quiet — but that cost must be accepted up front. A dev-only dependency still appears in composer.lock, Dependabot noise, and security-scan reports. The internal-adapter alternative costs more initially and far less over its lifetime; total cost of ownership favors the adapter for a Laravel-native team.

Support. No Laravel community, no Stack Overflow corpus, no first-party documentation for Illuminate. The support channel is the Happyr GitHub issue tracker, prioritized by consulting needs rather than user demand. Ramp-up is trivial for Symfony engineers and non-trivial for Laravel-only engineers, for whom compiler passes and kernel bootstrapping are foreign concepts.

Scaling. Negligible runtime cost: dev-only, test-environment-only, no production footprint, no per-request overhead. The real constraint is test-suite scale. Per-test container swapping tends to be heavier than Laravel's per-test $this->instance(); at thousands of tests the lighter native path wins.

Failure modes.

  • Service not found / private service — the compiler pass can only replace publicly reachable or explicitly declared services; opaque failures surface as "service does not exist" during kernel boot.
  • Silent non-mocking — if the code under test resolves the dependency via new or a static factory rather than the container, the mock is never injected and the test passes against the real service. This is the most dangerous failure mode and the one most likely to erode trust in the tool.
  • Final classes and readonly promoted properties resist mocking — common in modern codebases.
  • Version skew at Symfony/PHPUnit upgrades — container internals shift between majors and reflection assumptions break while CI shows green upstream.
  • In a Laravel context, the dominant failure is "nothing happens" — no bundle registration, wrong base test case, and the author concludes the package is broken rather than inapplicable.

Ramp-up. Symfony-familiar engineer: productive in under a day. Laravel-only engineer: two to three days before the compiled-container model clicks, plus recurring friction at every upgrade. If the decision is "adopt the concept, not the package," write it up once so the team does not re-litigate it each quarter.

TPM recommendation. Do not add happyr/service-mocking to a Laravel application; it solves a Symfony problem Laravel has already solved. Adopt the pattern via a small internal trait, or use the package directly only where a genuine Symfony surface exists. The 0.535 score and 29.15 opportunity score match that read: a well-made, narrowly scoped tool that is poorly matched to this stack. Frame it as a tactical convenience worth a one-sprint spike only if that spike proves Laravel's built-in fakes cannot reach the services we care about.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package