memio/spec-gen
Memio SpecGen is a PhpSpec extension that auto-generates constructors and methods from your specs, adding type-hinted arguments, sensible variable names, collision-safe numbering, and constructor properties/assignments.
Installation Update Composer requirements to reflect PHP 8.0+ and phpspec 6.3+:
composer require --dev memio/spec-gen:^0.10.1 phpspec/phpspec:^6.3
Verify compatibility by checking your php -v output (must be PHP 8.0+).
Basic Configuration
No additional config is required, but ensure phpspec/phpspec is updated to 6.3+ in composer.json:
"require-dev": {
"phpspec/phpspec": "^6.3",
"memio/spec-gen": "^0.10.1"
}
Test integration with:
vendor/bin/phpspec describe Your/ClassName
First Use Case
Generate a spec for a Laravel service class (e.g., app/Services/UserService.php):
vendor/bin/phpspec describe app/Services/UserService
The generator now leverages phpspec 6.3’s improved reflection for more accurate method detection in PHP 8.0+.
Laravel-Specific Spec Generation
Service Classes: Use --type=service to enforce Laravel’s dependency injection (now optimized for PHP 8.0’s constructor property promotion):
vendor/bin/phpspec describe app/Services/InvoiceService --type=service
Output includes stubs for promoted properties (e.g., #[Inject] public Repository $repository;).
Controllers: Leverage --type=controller for HTTP method stubs with PHP 8.0 attribute support:
vendor/bin/phpspec describe app/Http/Controllers/UserController --type=controller
Generated specs now include #[Route] attribute stubs (e.g., #[Route('users/{id}')]).
Customizing Spec Templates Publish and edit templates as before, but note phpspec 6.3’s stricter template validation:
php artisan vendor:publish --provider="Memio\SpecGen\SpecGenServiceProvider" --tag="spec-gen-templates"
Update resources/views/vendor/spec-gen/ to use PHP 8.0 syntax (e.g., #[Deprecated] annotations).
Integration with Laravel’s Testing
Use generated specs to bootstrap phpunit tests with PHP 8.0’s strict_types=1:
// In UserServiceSpec.php (auto-generated)
public function it_returns_a_user_by_id(): void {
$this->shouldThrow(ModelNotFoundException::class)->during('findUserById', [999]);
$this->beStrictAboutTypes()->whenTesting(UserService::class);
}
CI/CD Pipeline Update workflows to use PHP 8.0+ and phpspec 6.3:
# .github/workflows/spec-gen.yml
jobs:
generate-specs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
- run: composer require --dev memio/spec-gen:^0.10.1 phpspec/phpspec:^6.3
- run: vendor/bin/phpspec generate app/Services --format=pretty
PHP 8.0 Breaking Changes
--type=service to auto-detect promoted properties:
vendor/bin/phpspec describe --type=service app/Services/UserService
Manually adjust generated specs to use #[Inject] attributes if needed.Deprecated PHPDoc Syntax
@param mixed in favor of strict typing.strict_types=1 and use union types (e.g., @param array|int $id).Laravel Facade Mocking in PHP 8.0
Auth::shouldReceive()) may fail due to PHP 8.0’s stricter type system.getMockBuilder():
$this->getMockBuilder(Facade::class)
->disableOriginalConstructor()
->onlyMethods(['methodName'])
->getMock();
Performance with PHP 8.0 JIT
vendor/bin/phpspec generate --cache-dir=/tmp/spec-cache app/Services
vendor/bin/phpspec describe --debug --verbose app/Services/UserService
strict_types=1 to phpspec.yml to catch type-related issues early:
strict_types: true
PHP 8.0 Attribute Support
Extend the generator to handle custom attributes (e.g., Laravel’s #[Route]):
// app/Extensions/LaravelAttributeGenerator.php
use Memio\SpecGen\Generator\SpecGenerator;
class LaravelAttributeGenerator extends SpecGenerator {
protected function getMethodAnnotations(string $method): array {
$annotations = parent::getMethodAnnotations($method);
if (str_contains($method, 'store')) {
$annotations[] = '#[Route("users", methods: ["POST"])]';
}
return $annotations;
}
}
Union Types in Specs Override property generators to support PHP 8.0 union types:
// app/Extensions/UnionTypeGenerator.php
use Memio\SpecGen\Generator\PropertyGenerator;
class UnionTypeGenerator extends PropertyGenerator {
public function generateForProperty(string $property): string {
return "public function set{$property}(array|string \$value): void {}";
}
}
PHP 8.0 Enums
Add support for Laravel’s enum classes (e.g., UserStatus::Active):
// In a custom extension
$this->shouldReturn(UserStatus::Active)->when('getStatus')->isCalled();
How can I help you explore Laravel packages today?