【问题标题】:Factory relationship returning null laravel testing工厂关系返回 null laravel 测试
【发布时间】:2021-07-08 22:01:30
【问题描述】:

我正在尝试对在 Laravel 中处理用户注册的服务进行单元测试。

这是服务:

public function completeRegistration(Collection $data)
    {
        $code = $data->get('code');
        $registerToken = $this->fetchRegisterToken($code);

        DB::beginTransaction();

        $registerToken->update(['used_at' => Carbon::now()]);
        $user = $this->userRepository->update($data, $registerToken->user);
        $token = $user->createToken(self::DEFAULT_TOKEN_NAME);

        DB::commit();

        return [
            'user' => $user,
            'token' => $token->plainTextToken,
        ];
    }

update 方法具有以下签名:

<?php

namespace App\Repositories\User;

use App\Models\User;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;

interface UserRepositoryInterface
{
    public function create(Collection $data): User;
    public function update(Collection $data, User $user): User;
}

我的测试是:

/**
     * Test a user can register
     *
     * @return void
     */
    public function test_user_can_complete_registration()
    {
        $userRepositoryMock = Mockery::mock(UserRepositoryInterface::class);
        $registerTokenRepositoryMock = Mockery::mock(RegisterTokenRepository::class);
        $userFactory = User::factory()->make();
        $registerTokenFactory = RegisterToken::factory()
            ->for($userFactory)
            ->timestamped()
            ->make(['user_id' => $userFactory->id]);

        dd($registerTokenFactory->user);

        $userRepositoryMock
            ->expects($this->any())
            ->once()
            ->andReturn($userFactory);

        ....

    }

当我运行phpunit --filter=test_user_can_complete_registration 时出现以下错误:

1) Tests\Unit\Services\Auth\AuthServiceTest::test_user_can_complete_registration
TypeError: Argument 2 passed to Mockery_0_App_Repositories_User_UserRepositoryInterface::update() must be an instance of App\Models\User, null given, called in /var/www/app/Services/Auth/AuthService.php on line 64

/var/www/app/Services/Auth/AuthService.php:64
/var/www/tests/Unit/Services/Auth/AuthServiceTest.php:88

这告诉我$registerTokenFactory 上的user 关系为空。当我这样做时:

public function test_user_can_complete_registration()
{
   ...
   dd($registerTokenFactory->user);
}

我得到了输出null。我正在尝试在不访问数据库的情况下测试服务。如何将user 关系附加到$registerTokenFactory 对象?我尝试使用for 并尝试直接附加:

$registerTokenFactory = RegisterToken::factory()
            ->for($userFactory)
            ->timestamped()
            ->make(['user_id' => $userFactory->id, 'user' => $userFactory]);

【问题讨论】:

    标签: php laravel unit-testing phpunit


    【解决方案1】:

    Laravel 工厂make() 只创建模型而不保存它。为了使关系起作用,您需要保存模型。

       $userFactory = User::factory()->create();
    

    由于您不想使用数据库,我认为这是错误的。人们不喜欢编写测试,所以当我们必须让它变得简单时,模拟一切以避免数据库是一种痛苦。相反,您可以使用Sqlite 在内存中快速轻松地运行。一个缺点是某些功能在 JSON 字段中不起作用,并且大多数 Ubuntu 发行版中的版本不尊重外键。

    如果你想遵循你已经在的路径,分配对象上的用户会起作用,你有一些我假设的代码遗漏。

    $userRepositoryMock = Mockery::mock(UserRepositoryInterface::class);
    $registerTokenRepositoryMock = Mockery::mock(RegisterTokenRepository::class);
    
    $user = User::factory()->make();
    
    $registerToken = RegisterToken::factory()
        ->for($userFactory)
        ->timestamped()
        ->make(['user_id' => $user->id]);
    
    $registerToken->user = $user;
    
    $registerTokenRepositoryMock
        ->expects('fetchRegisterToken')
        ->once()
        ->andReturn($registerToken);
    
    $userRepositoryMock
        ->expects($this->any())
        ->once()
        ->andReturn($user);
    
    // execute the call
    

    【讨论】:

      猜你喜欢
      • 2014-08-21
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      • 2012-08-13
      相关资源
      最近更新 更多