调用另一个工厂内的工厂

问题描述 投票:0回答:2

我目前正在学习如何使用 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。

laravel phpunit laravel-5.6
2个回答
7
投票

您可以通过将包含要覆盖的属性和值的数组传递给

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,则可以阻止创建另一个用户。

重写属性文档


1
投票

作为一个小更新,对于 Laravel 8,语法为:

$factory->define(Book::class, function (Faker $faker) {
    return [
        'title'     => $faker->sentence,
        'author'    => $faker->name,
        'user_id'   => User::factory()->create()->id
    ];
});
© www.soinside.com 2019 - 2024. All rights reserved.