Pest 本身不支持架构测试,需额外安装 pestphp/pest-plugin-architecture 插件;该插件基于 AST 分析依赖关系,要求 PHP 8.1+ 和 Pest v2.20+,并需在 tests/Arch.php 中配置路径、用 –arch 参数运行。

为什么 composer require pestphp/pest --dev 装不上架构测试功能
因为 Pest 本身不内置架构测试能力,pestphp/pest 包只提供测试运行器和基础断言;架构约束(比如“控制器不能依赖仓储层”)需要额外扩展。装完基础 Pest 后,必须手动加 pestphp/pest-plugin-architecture 才能写 it('has correct layer dependencies') 这类断言。
- 直接运行
composer require pestphp/pest-plugin-architecture --dev,它会自动注册插件并加载架构 DSL - 该插件依赖 PHP 8.1+ 和 Pest v2.20+,低版本会静默失败或报
Class "PestPluginArchitecture" not found - 如果项目已用 Laravel Pint 或 PHP-CS-Fixer,注意它们不检查目录间耦合,架构测试是唯一能捕获“AppHttpControllersUserController 用了 AppRepositoriesUserRepository”的工具
怎么写第一条架构测试:避免 app/Http 层引用 app/Models 以外的领域层
真实项目里最容易破防的是控制器偷偷 new 一个仓储类,或者请求类里调用了领域服务——这类问题单元测试发现不了,只有架构测试能卡住。
- 在
tests/Arch.php里写:uses(TestsFeatureArchTest::class)->in('Arch'); - 新建
tests/Arch/HttpLayerTest.php,内容为:it('does not let Http layer depend on Repositories or Services')<br> ->expect(['AppHttpControllers', 'AppHttpRequests'])<br> ->not->haveDependencyOn(['AppRepositories', 'AppServices']); - 注意路径字符串必须和
composer.json的"autoload": {"psr-4": {……}}完全一致,大小写错一个字母就匹配失效 - 运行
./vendor/bin/pest --arch才会触发架构测试;默认./vendor/bin/pest不跑tests/Arch目录
haveDependencyOn 和 not->haveDependencyOn 的行为差异
这两个方法不是简单的白名单 / 黑名单开关,而是基于 AST 静态分析类引用关系,对 use、new、类型提示、返回类型都生效,但对字符串类名(如 app('xxx'))和反射调用无感。
-
haveDependencyOn(['AppModels'])表示「必须存在至少一处从当前命名空间到 Models 的依赖」,适合验证「Controller 确实用了 Model」 -
not->haveDependencyOn(['AppRepositories'])表示「任何地方都不能出现 Repository 的硬依赖」,这是分层架构的守门员 - 如果某 Controller 用到了
AppRepositoriesUserRepository,但该类被 interface + binding 解耦(即 type-hint 接口,容器注入实现),架构测试仍会报警——因为它看的是实际引用的类,不是绑定逻辑 - 想绕过误报?只能用
ignoreFiles()显式排除,比如->ignoreFiles(['app/Console/Commands'])
CI 中跑架构测试失败但本地正常?查这三点
常见于 GitHub Actions 或 GitLab CI,根本原因是 autoload 生成策略和开发环境不一致,导致 AST 分析时找不到类定义。
- 确认 CI 中执行了
composer install --no-dev❌ —— 架构测试是--dev依赖,必须用composer install(或至少composer install --with-all-dependencies) - 检查
composer.json的"autoload-dev"是否包含tests/Arch,漏掉会导致TestsArch*类无法被自动加载 - PHP 版本差异:本地 PHP 8.2,CI 用 8.1,而
pest-plugin-architecturev2.3+ 要求 8.2+;降级插件或升级 PHP 可解,错误信息通常是ParseError: syntax error, unexpected token "readonly"
架构测试真正难的不是写断言,而是定义清楚“什么算违规”。比如是否允许 Facade、是否接受 DTO 经过 HTTP 层、第三方 SDK 放在哪一层——这些规则一旦定下来,就别让 ignoreFiles 或注释临时绕过,否则很快就会变成形同虚设的装饰品。