我目前正在学习如何使用 Laravel 应用程序编写 PHPUnit 测试,但几天来却遇到了困难。我的测试是,如果用户的 id 与图书的用户 id 相同,则仅允许经过身份验证的用户更新图书记录。
public function test_onlyAuthenticatedUserCanUpdateBookSuccessfully()
{
$user = factory(User::class)->create();
Passport::actingAs($user);
$book = factory(Book::class)->create();
dd($user, $book);
// $response = $this->json('PUT', '/api/books/'.$book->id, [
// 'id' => $book->id,
// 'title' => 'Updated book title',
// 'author'=> 'New Guy'
// ]);
// $response->assertStatus(201);
}
但是我最初遇到了 403 错误,在排除故障时,我从转储的数据中注意到创建的用户 id 与书籍的 user_id 不同。
// Newly created user
#original: array:7 [
"name" => "Prof. Norwood Erdman"
"email" => "[email protected]"
"updated_at" => "2018-10-03 14:11:20"
"created_at" => "2018-10-03 14:11:20"
"id" => 2
]
// Newly created book
#attributes: array:6 [
"title" => "Quasi laudantium enim quas omnis."
"author" => "Mr. Jayson Roob"
"user_id" => 1
"updated_at" => "2018-10-03 14:11:20"
"created_at" => "2018-10-03 14:11:20"
"id" => 3
]
查看我的代码,我发现每次创建一本书时,user_id 都会设置为 1,因为我的 BooksFactory 使用硬编码值
user_id = 1
。
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'author' => $faker->name,
'user_id' => 1
];
});
如何编写代码,以便在创建书籍时的测试中,将经过身份验证的用户 id 指定为书籍的用户 id?我认为这会解决测试问题。我使用 sqlite 内存数据库进行测试,而不是 mysql。
您可以通过将包含要覆盖的属性和值的数组传递给
create()
方法来覆盖工厂中的属性:
$book = factory(Book::class)->create(['user_id' => $user->id]);
此外,在工厂本身中创建用户可能是一个好主意,即:
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'author' => $faker->name,
'user_id' => function () {
return factory(App\User::class)->create()->id;
}
];
});
将
user_id
值封装在闭包中的原因是,如果您想传递自己的 id,则可以阻止创建另一个用户。
作为一个小更新,对于 Laravel 8,语法为:
$factory->define(Book::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'author' => $faker->name,
'user_id' => User::factory()->create()->id
];
});