- How do I install pkly/phpunit-service-create-trait?
- Install it as a dev dependency with composer require --dev pkly/phpunit-service-create-trait. There is no service provider, config file, or bootstrap change involved; the package publishes nothing. You then add the ServiceMockHelperTrait to any PHPUnit test case where you want it, and existing tests that do not use the trait are unaffected.
- What PHP and PHPUnit versions does this trait require?
- The README states PHP 8.4 or newer and PHPUnit 12 or 13. That is a hard floor: Laravel 11 and 12 projects commonly run PHPUnit 10 or 11 on PHP 8.2 or 8.3, so many teams would have to upgrade PHPUnit, PHP, or both before installing. Treat adoption as an infrastructure decision rather than a testing-tooling one and confirm the floors are genuine before piloting.
- Does the trait work with Laravel's Tests\TestCase and RefreshDatabase?
- Yes. The trait is additive and only calls PHPUnit's own createMock and createStub internals, so it composes with Tests\TestCase, RefreshDatabase, data providers, and existing createMock usage in the same class. You can adopt it in a single test class and leave the rest of the suite untouched. Pest support is not documented, so verify it yourself before relying on it.
- How does createRealMockedServiceInstance() build the service?
- It reflects over the class constructor, creates a test double for every typed parameter, and instantiates the service immediately with new. Dependencies are handed over as invisible stubs that PHPUnit never verifies, so there are no 'no expectations configured' warnings. Because construction happens up front, you can declare expectations before or after creating the service without ordering problems.
- What is the difference between getMockedService() and getStubbedService()?
- getMockedService() registers the double with the test case and returns it as a MockObject, so expects() calls are verified and PHPUnit will complain if you configure nothing. getStubbedService() returns the same object as a Stub and leaves it unregistered, which is what you want when you only need to set return values. Anything you never fetch stays invisible to PHPUnit entirely.
- Does the trait respect Laravel service container bindings?
- No. It constructs services with new and hand-assembled doubles, deliberately bypassing the container. Container bindings, contextual resolution, decorators, config-driven factories, service-provider aliasing, and Laravel's #[Inject] attribute are all absent from the object under test. For a pure domain service with interface-typed dependencies that is exactly right, but for anything relying on container semantics the test verifies wiring that does not exist in production.
- What happens with final classes, enums, variadics, or union types?
- These are the weak spots. Final classes, enums, scalars without defaults, variadics, union and intersection types, self and parent hints, and some internal PHP classes cannot be auto-doubled cleanly, so they surface as setUp() failures that force per-parameter overrides. That erodes the boilerplate savings on exactly the constructors you were trying to avoid maintaining. Error quality is not documented, so audit the failure path before rolling it out broadly.
- Does it support Symfony's #[Required] attribute in a Laravel codebase?
- The trait will populate methods marked with Symfony's #[Required] attribute automatically, but that attribute is Symfony autowiring and has no direct Laravel equivalent. In a Laravel codebase that half of the feature set is effectively inert. Only the constructor-injection half is likely to matter to you, so evaluate the package on that basis.
- Is pkly/phpunit-service-create-trait safe to add to my project?
- Supply-chain exposure is low: it is require-dev only, MIT licensed, has a small surface, and never ships in production artifacts. The real risk is false confidence from container divergence and breakage when PHPUnit reaches into its internals, since the trait depends on PHPUnit's mock registry. The code is small enough to audit in an afternoon and fork in a day, so read it before depending on it.
- Is this package maintained, and what are the alternatives?
- Maturity signals are thin: zero stars, zero dependents, a single maintainer, a handful of releases, and README-only documentation. Treat it as a credible pattern but an unproven dependency. Alternatives are explicit createMock calls in setUp(), Laravel's $this->mock() and $this->instance() container bindings combined with app()->make(), or Mockery, all of which keep you inside container semantics if that matters to your tests.