odinns / phpstan-pest-this
PHPStan extensions to infer Pest closure $this type from test file mappings.
Package info
github.com/odinns/phpstan-pest-this
Type:phpstan-extension
pkg:composer/odinns/phpstan-pest-this
Requires
- php: ^8.3
- phpstan/phpstan: ^2.1.38
Requires (Dev)
- phpunit/phpunit: ^12.5
README
PHPStan extensions that infer Pest closure $this type from configurable test-path mappings.
Why
Pest binds test closures at runtime, while PHPStan analyzes code statically.
Without extra help, closure $this is commonly inferred as PHPUnit\Framework\TestCase, which can produce false positives in Pest suites.
Installation
composer require --dev odinns/phpstan-pest-this
Quick setup
Add the extension to your PHPStan config:
includes: - vendor/odinns/phpstan-pest-this/extension.neon
The extension does not provide default test case mappings. Configure how file paths map to your Pest base test case classes:
parameters: pestClosureThisTypeMap: - pathContains: '/tests/' class: Tests\TestCase
This is the common Laravel/Pest setup where feature and unit tests share Tests\TestCase.
If your project uses separate base test cases, map the more specific paths explicitly:
parameters: pestClosureThisTypeMap: - pathContains: '/tests/Feature/' class: Tests\Feature\TestCase - pathContains: '/tests/Unit/' class: Tests\Unit\TestCase
pathContains is a substring match against the analyzed file path. The first matching mapping wins.
Supported Pest calls
- Function calls:
it(...),test(...),beforeEach(...),afterEach(...) - Fluent hooks:
uses(...)->beforeEach(...),uses(...)->afterEach(...)
Optional: Generate a PHPStan proxy test case
If your base test case has protected assertion helpers, PHPStan may flag visibility errors from Pest closures. Use the included generator to create a static-analysis-only proxy class with public wrappers.
After installation:
vendor/bin/generate-pest-proxy.php \ --source="Tests\\Feature\\TestCase" \ --target="tests/PHPStan/PestFeatureTestCase.php" \ --namespace="Tests\\PHPStan" \ --class="PestFeatureTestCase"
While developing this package locally:
php tools/generate-pest-proxy.php \ --source="Tests\\Feature\\TestCase" \ --target="tests/PHPStan/PestFeatureTestCase.php" \ --namespace="Tests\\PHPStan" \ --class="PestFeatureTestCase"
Then map the relevant directory to the generated proxy:
parameters: pestClosureThisTypeMap: - pathContains: '/tests/Feature/' class: Tests\PHPStan\PestFeatureTestCase
This proxy only affects static analysis. It does not change Pest runtime behavior.
Limitations
- The extension resolves closure
$thistype only. - It does not infer dynamic properties automatically; declare those on your test case/traits.
- Mapping is path-substring based, so very broad patterns can match unintentionally.
Development
composer install composer check
Troubleshooting
- No effect in analysis: confirm
extension.neonis included in your PHPStan config. - Wrong inferred class: ensure mapping order is specific to broad (first match wins).
- Generator not found: use
vendor/bin/generate-pest-proxy.phpafter install orphp tools/generate-pest-proxy.phpin this repository.
Versioning
This package follows SemVer from 1.0.0 onward. Composer versions come from Git tags, not a version field in composer.json.
Contributing
Keep changes narrow. This package teaches PHPStan about Pest closure $this; it should not grow runtime Pest behavior or framework glue.
Run composer check before opening a PR.
Security
Report security issues privately through GitHub Security Advisories:
https://github.com/odinns/phpstan-pest-this/security/advisories/new
Please do not open public issues for security reports.
Changelog
See CHANGELOG.md for release notes.
License
MIT