模拟 Eloquent 模型 returns 数组而不是模型

Mocked Eloquent Model returns array instead of Model

奇怪的问题: mocked模型returns的方法first一个array而不是型号.

见下面的代码(Laravel + Eloquent + PHPUnit + Mockery)。

Eloquent 型号

public function getByEmail(string $email) : User
{
    return $this->whereHas('emails', function ($query) use ($email) {
        $query->where('email', $email);
    })->first();
}

这很好用。它 returns 一个 User 类型的模型。

存储库

public function getByEmail(string $email) : array
{
    return $this->model->getByEmail($email)->toArray();
}

哪个也很好:-)

用 Mockery 测试

/** @test */
public function it_fetches_an_user_by_email()
{
    $email = 'foo@bar.foo';

    $this->userMock
        ->shouldReceive('getByEmail')
        ->once()
        ->with($email)
        ->andReturn(['user' => 'foo']);

    $userRepository = new UserEloquentRepository($this->userMock);
    $this->assertArrayHasKey('user', $userRepository->getByEmail($email));
}

我现在的问题::模拟模型的方法first returns 一个数组 而不是型号.

first() 从未被调用。

你的测试中有这个:

$this->userMock
    ->shouldReceive('getByEmail')
    ->once()
    ->with($email)
    ->andReturn(['user' => 'foo']);

这是告诉模拟用户对象在调用 getByEmail 时要 return 什么;你已经告诉它 return 一个数组 (['user' => 'foo'])。它实际上从未在您的 User 模型上调用 getByEmail 方法。

编辑

您在User模型上定义的方法没有被调用;您正在使用模拟对象。在您的测试中,当您在存储库上调用 getByEmail() 时,它会在您的模拟对象上调用 getByEmail()。当调用 getByEmail() 时,您已经告诉模拟对象 return 数组 (['user' => 'foo'])。

你需要告诉你的模拟对象 return 正确的数据(这是一个 User 对象,而不是数组)。

试试这个:

$this->userMock
    ->shouldReceive('getByEmail')
    ->once()
    ->with($email)
    ->andReturn(new \App\User(['user' => 'foo']));

或者将 return 定义为另一个应接收 toArray() 方法和 return 数组 ['user' => 'foo'].

的模拟用户对象