【问题标题】:How to mock Laravel's eloquent accessor attribute如何模拟 Laravel 雄辩的访问器属性
【发布时间】:2015-08-20 07:09:57
【问题描述】:

我正在我的 Laravel 4 应用程序中实现单元测试,但我被困在模拟访问器属性上。

我有一个 Eloquent 模型,其中有一个 Accessor 属性。我正在尝试模拟此模型并在调用此访问器属性时返回一个值。但我找不到任何解决方案让它发挥作用。

我的超级简单的用户类。

class User extends Eloquent {
    public function getFullNameAttribute() {
        return $this->first_name . ' ' . $this->last_name;
    }
}

我尝试了以下方法:

$user_mock = m::mock('MyApp\Models\User');

$user_mock->shouldReceive('__get')->with('full_name')->andReturn('John Snow'); // doesn't work
$user_mock->shouldReceive('getAttribute')->with('full_name')->andReturn('John Snow'); // doesn't work
$user_mock->shouldReceive('getFullNameAttribute')->andReturn('John Snow'); // doesn't work

echo $user_mock->full_name; // --> " "

我只是得到一个空的空间,说明原来的函数还在被调用。

【问题讨论】:

    标签: php laravel-4 mockery


    【解决方案1】:

    尽量不要嘲笑雄辩的模型。这是“模拟您不拥有的类型”的示例。如果 Laravel 在新版本中更改了雄辩的内部结构,并且您在单元测试中模拟了它们,那么您的测试可能会提供误报。

    此外,我认为尝试嘲笑它们很奇怪。您会失去这些实体映射到现实世界事物的想法,而需要隔离测试的是业务逻辑组件(模拟依赖项)。

    在使用访问器时,我发现将其包装在另一个抽象中很有帮助,例如在存储库层中:

    public function getFirstNameAttribute()
    {
         return app(UserRepository::class)->getFirstName($this);
    }
    

    我发现访问器使客户端代码具有极强的可读性。这是完全可测试的,并且与数据库的整个交互都是可模拟的,如果您有数千个测试,这可能有助于减少开销。

    【讨论】:

      【解决方案2】:

      查看 Mockery 的文档,它似乎不支持模拟魔术方法。您基本上只需要使用普通赋值来设置属性:

      $user_mock = m::mock('MyApp\Models\User');
      $user_mock->first_name = 'John Snow';
      

      Mockery docs

      【讨论】:

      • 为什么这被否决了?这不行吗?不要没有明确的理由投反对票,如果你这样做,请添加评论解释。
      • 尝试像普通对象一样静态设置模型的属性是行不通的。因为 Laravel 使用 getter 方法来访问属性。
      • 我不同意,创建部分模拟(M::mock('MyApp\Models\User')->makePartial(); 可以解决问题
      • 如果您尝试设置要从访问器返回的值,这将无济于事,因为访问器可能会在返回值之前对其进行修改。因此,您可能不会收到您期望的确切值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 2021-08-11
      • 2017-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多