【问题标题】:Eloquent Model Events in Laravel 5.1 Testing EnvironmentLaravel 5.1 测试环境中的 Eloquent 模型事件
【发布时间】:2015-10-11 02:34:42
【问题描述】:

我有一个Eloquent 模型,我在模型的boot() 方法中定义了一些观察者方法。这是一个非常简单的逻辑——如果在调用Model::create([...]) 时没有定义属性,我会使用creating() 静态方法来定义属性的默认值。

protected static function boot()
{
    parent::boot();
    static::creating(function (Content $content) {
        static::setDefaultValues($content);
    });
}

protected static function setDefaultValues(Content $content)
{
    if ( ! $content->published_at) {
        $content->published_at = Carbon::now();
    }
}

通过浏览器或使用artisan tinker 的控制台或数据库播种器使用应用程序时,一切正常。

但是,当我在测试用例运行时尝试使用相同的数据库播种逻辑通过 artisan 命令引导测试数据库时,会抛出异常,指出特定属性不能为 NULL。我做了一些研究和挖掘 Laravel 代码,发现 Event Dispatcher 应该可以正常运行,因为我没有模拟任何事件,也没有使用 withoutEvents() helper。

此外,全局范围似乎不适用于测试环境。

我已经将 var_dumps 放置在几个关键点上(在调用 creating() 之后,在 save() 方法中的 Eloquent\Model 类中以及在触发模型事件之后)检查属性并注意到观察者方法 正在执行,但效果好像模型实例不是通过引用传递给事件处理程序,而是克隆。相同的代码在开发环境中运行正常,但在测试环境中描述失败。

有没有人遇到过这样的事情?我不确定如何继续,所以非常欢迎任何建议。

对于它的价值,我在开发中使用 MySQL 并尝试在 SQLite 数据库中运行测试以方便使用。测试是使用 Laravel 开箱即用的 PHPUnit 测试设置运行的。

【问题讨论】:

    标签: php unit-testing phpunit eloquent laravel-5


    【解决方案1】:

    将所有模型事件绑定的声明移至 AppServiceProvider::boot() 方法,如下所示

    class AppServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            \App\Content::creating(function (Content $content) {
                $content::setDefaultValues($content); // change to public
            });
    
            // other bindings
        }
    
        /**
         * Register any application services.
         *
         * @return void
         */
        public function register()
        {
            //
        }
    }
    

    关注http://laravel.com/docs/5.1/eloquent#events

    您也可以使用该方法来附加模型观察者。

    【讨论】:

    • 你可以使用更通用的吗?例如模型类??
    • 我尝试使用 BaseModel 类并调用 BaseModel::creating 但不起作用
    • 我不这么认为,因为事件调度器使用模型类名来格式化事件名。看看 Model::fireModelEvent($event)。因此,“eloquent.creating User”与“eloquent.creating BaseModel”不匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2016-11-15
    • 2015-09-12
    • 2018-11-23
    • 2023-03-22
    • 2015-02-15
    相关资源
    最近更新 更多