无法使用assertSet测试laravel livewire模型隐藏属性



我有一个简单的LIvewire组件,它由一个创建新用户的表单组成,我可以看出它是有效的,因为我被要求在项目进入阶段后编写测试。

Livewire组件在持久化插入的数据之前使用new User实例(未预先列出,即user->existsfalse(来存储插入的数据,而user模型通过受保护的$hidden数组隐藏密码属性。

现在,我可以在本地环境中通过表单页面成功地创建新用户,但在测试时,这会给我带来错误。

测试

Livewire::test(
FormComponent::class,
)
->set('user.name', 'user name')
->set('user.email', 'user@email.com')
->set('user.password', 'password')
->assertSet('user.name', 'user name')
->assertSet('user.email', 'user@email.com')
->assertSet('user.password', 'password');

错误

Failed asserting that null matches expected 'password'.

我发现了什么

通过表单页面设置我的组件用户实例很好,因为livewire将其识别为model,所以可以执行类似user->password = 'password'的操作,而当使用set()从测试中设置它时,它会使用访问运算符访问它的属性,因为它是一个数组,即:user['password] = 'password'
注释掉$hidden数组中的密码条目使测试通过。这将解释属性设置的差异。

结论

由于$hidden数组旨在将模型属性隐藏在其array/json表示中,因此它不应干扰自动测试,而且在使用Livewire自己的方法时,所以对我来说,这看起来像是一个Livewire Bug。

帮助

有人遇到过这个错误吗?

更新#1

我在Livewire github页面上为此打开了一个问题。

您已经很好地诊断了这一点。Livewire序列化User模型时,password不包括在内,因为它位于$hidden数组中。即使用户模型还没有持久化,序列化也是一样的。

我猜您的输入字段都使用defer修饰符,这就是为什么您的字段在浏览器中工作的原因;但是,当您在测试中调用set()时,它会模拟Livewire请求,因此$hidden属性将被擦除。

我在这里建议使用另一种测试密码的断言。尝试断言创建的用户可以使用所选密码登录。

$this->assertTrue(
auth()->attempt(['email' => 'user@email.com', 'password' => 'password'])
);

最新更新