odinns/phpstan-pest-this
phpstan-pest-this
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
Related Packages
The most comprehensive WordPress testing framework built on Pest PHP v4. Include...
One command sets up Claude Code (and any AI coding agent) on a Laravel project:...
🧪 Tools needed for PHP and Laravel project development and automation.