工厂关系返回 null laravel 测试
Factory relationship returning null laravel testing
我正在尝试对处理 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]);
在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
我正在尝试对处理 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]);
在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