Laravel 7 - 如何在 Validator::extend() 上重新绑定存储库以进行测试?

Laravel 7 - How do I rebind repository on Validator::extend() for tests?

我设置了这样的自定义验证规则:

// 自定义创建 RepositoryProvider.php 也注册在 app.php 'providers' 数组中。

public $bindings = [
    UserRepository::class => EloquentUserRepository::class,
];

public function boot(UserRepository $userRepository)
{
    Validator::extend('user_email_unique', function($attribute, $value, $parameters) use($userRepository) {
        return !$userRepository->findByEmailAddress($value)->exists();
    });
}

//我的测试

class SignUpUserActionTest extends TestCase
{
    public function setUp() : void
    {
        parent::setUp();

        $this->app->bind(UserRepository::class, function() {
            return new UserRepositoryMock();
        });
    }
}

在我的测试中,我将 UserRepository 重新绑定到模拟。它在获取数据方面工作得很好,但它保留了验证扩展的原始绑定并且不重新绑定所使用的存储库。因此,当单元测试 运行.

时,他们使用两种不同的实现

我如何扩展验证器,以便自动解决方案在测试中反弹?

谢谢。

由于您在 RepositoryProvider 中执行逻辑,这将在您的 parent::setUp() 调用中实例化,从而在绑定被模拟之前获取您的 UserRepository。在此调用之前移动绑定,我假设您会得到不同的结果。

public function setUp() : void
{
    $this->app->bind(UserRepository::class, function() {
        return new UserRepositoryMock();
    });

    parent::setUp();
}

编辑

根据您的评论,原因是正确的,解决方案是错误的。在闭包中解析 UserRepository,很可能会在设置绑定时解析它。

Validator::extend('user_email_unique', function($attribute, $value, $parameters) {
    $userRepository = resolve(UserRepository::class);
    return !$userRepository->findByEmailAddress($value)->exists();
});