Laravel 8+Livewire 2.7.2测试报Undefined index: fingerprint如何解决
Laravel 8 + Livewire 2.7.2 测试CRUD功能fingerprint缺失报错解决方案
问题描述
在Laravel 8 + Livewire 2.7.2版本项目中编写管理端设施CRUD功能的测试用例时,触发Undefined index: fingerprint错误。
相关代码与错误信息
1. 测试文件
文件路径:tests/Feature/AdminFacilitiesCrud.php
<?php namespace Tests\Feature; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithFaker; use Tests\TestCase; use Livewire\Livewire; use App\Models\User; use App\Models\Facility; use Livewire\Component; use Illuminate\Database\QueryException; use App\Http\Livewire\Admin\CrudFacilities; use DB; class AdminFacilitiesCrud extends TestCase { /** @test */ public function can_create_facility_under_admin_crud() { $newUser= User::factory()->create(); $this->actingAs($newUser); Livewire::test(CrudFacilities::class) ->set('name', 'New Facility name ') ->set('descr', 'New Facility description text... ') ->call('store'); $this->assertTrue(Facility::getByName('foo')->exists()); } }
2. 错误输出
master@master-laptop:/mnt/_work_sdb8/wwwroot/lar/hostels4j$ ./vendor/bin/phpunit tests/Feature/AdminFacilitiesCrud.php PHPUnit 9.5.10 by Sebastian Bergmann and contributors. Runtime: PHP 7.4.25 Configuration: /mnt/_work_sdb8/wwwroot/lar/hostels4j/phpunit.xml E 1 / 1 (100%) Time: 00:00.269, Memory: 28.00 MB There was 1 error: 1) Tests\Feature\AdminFacilitiesCrud::can_create_facility_under_admin_crud ErrorException: Undefined index: fingerprint /mnt/_work_sdb8/wwwroot/lar/hostels4j/vendor/livewire/livewire/src/Testing/TestableLivewire.php:179 /mnt/_work_sdb8/wwwroot/lar/hostels4j/vendor/livewire/livewire/src/Testing/Concerns/MakesCallsToComponent.php:142 /mnt/_work_sdb8/wwwroot/lar/hostels4j/vendor/livewire/livewire/src/Testing/Concerns/MakesCallsToComponent.php:87 /mnt/_work_sdb8/wwwroot/lar/hostels4j/vendor/livewire/livewire/src/Testing/Concerns/MakesCallsToComponent.php:74 /mnt/_work_sdb8/wwwroot/lar/hostels4j/vendor/livewire/livewire/src/Testing/Concerns/MakesCallsToComponent.php:56 /mnt/_work_sdb8/wwwroot/lar/hostels4j/tests/Feature/AdminFacilitiesCrud.php:33
3. 已尝试无效的方案
- 测试类中声明
$fingerprint公共属性 - 测试链式调用中手动执行
set('fingerprint')赋值 - 执行
composer update livewire/livewire更新Livewire版本 - 执行
php artisan view:clear清理视图缓存 - 执行
php artisan livewire:publish --assets重新发布静态资源
4. 对应Livewire组件代码
文件路径:app/Http/Livewire/Admin/CrudFacilities.php
<?php namespace App\Http\Livewire\Admin; use App\Models\Facility; use Livewire\Component; use Illuminate\Database\QueryException; use App\Models\Settings; use App\Library\CheckValueType; use Livewire\WithPagination; use DB; class CrudFacilities extends Component { use WithPagination; public $form= [ 'name'=>'', 'descr'=> '', 'created_at'=> '', 'is_reopen' => false, ]; public $current_facility_id; public $filter_name= ''; public $filter_extended_search= ''; public $updateMode = 'browse'; protected $listeners = ['openFacilityInEditor' => 'edit', 'addNewItem' => 'add']; public function render() { // 省略渲染逻辑 } public function store() { \Log::info( '-1 store ::' . print_r( -1, true ) ); $this->validate( Facility::getFacilityValidationRulesArray($this->current_facility_id), Facility::getValidationMessagesArray() ); \Log::info( '-2 store $this->form ::' . print_r( $this->form, true ) ); // 省略存储逻辑 } }
5. 报错根因
报错出现在vendor/livewire/livewire/src/Testing/TestableLivewire.php的pretendWereSendingAComponentUpdateRequest方法中,访问$this->payload['fingerprint']时该索引不存在,该调用由MakesCallsToComponent.php中的updateProperty方法触发。
问题解答
1. 项目内复写相关类的方法
可以通过Laravel服务容器绑定覆盖原生类实现:
- 新建
app/Overrides/Livewire/TestableLivewire.php文件,将vendor目录下对应TestableLivewire.php的内容复制到该文件 - 修改
pretendWereSendingAComponentUpdateRequest方法,在访问fingerprint索引前添加判空逻辑:if (!isset($this->payload['fingerprint'])) { $this->payload['fingerprint'] = [ 'id' => $this->component->id, 'name' => $this->component->getName(), 'locale' => app()->getLocale(), ]; } - 在
app/Providers/AppServiceProvider.php的register方法中添加绑定:$this->app->bind(\Livewire\Testing\TestableLivewire::class, \App\Overrides\Livewire\TestableLivewire::class);
2. updateProperty方法说明
updateProperty是Livewire测试工具的内部方法,作用是模拟前端发起的组件属性更新请求,同步服务端组件的公共属性值。
不需要手动调用该方法设置fingerprint,fingerprint属于Livewire内部维护的请求元数据,不属于组件的公共属性,通过set方法或直接调用updateProperty都无法给内部payload的fingerprint字段赋值。
3. 其他可行解决方案
- 修复测试代码的属性名错误(核心问题):你的组件中
name和descr是$form数组的键,没有顶层的$name、$descr公共属性,测试代码中->set('name')写法非法,会触发Livewire内部处理异常,导致payload生成中断。修改为正确的数组属性写法即可:Livewire::test(CrudFacilities::class) ->set('form.name', 'New Facility name ') ->set('form.descr', 'New Facility description text...') ->call('store'); - 测试类引入
RefreshDatabasetrait,避免数据库初始化异常导致组件渲染失败、payload生成不完整。 - 降级Livewire到2.6.x稳定版,2.7.2版本的测试工具存在已知的payload生成逻辑漏洞,部分低版本不存在该问题。
- 调用测试方法前先执行一次属性校验,触发完整的组件初始化流程,补全payload:
Livewire::test(CrudFacilities::class) ->assertSet('updateMode', 'browse') ->set('form.name', 'New Facility name ') // 后续逻辑
内容的提问来源于stack exchange,提问作者mstdmstd
相关产品推荐
相关产品推荐

