呼叫另一个工厂内的工厂

时间:2018-10-03 14:40:15

标签: laravel phpunit laravel-5.6

我目前正在学习如何使用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" => "ihoeger@example.com"
    "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
]

在我的代码中,我发现每次创建一本书时,由于我的BooksFactory使用的是user_id = 1的硬编码值,因此user_id将设置为1。

$factory->define(Book::class, function (Faker $faker) {
return [
    'title'     => $faker->sentence,
    'author'    => $faker->name,
    'user_id'   => 1
];
});

如何编写代码,以便在创建图书的测试中,将经过身份验证的用户ID分配为图书的用户ID?我认为这将解决测试。我正在使用sqlite内存数据库进行测试,而不是mysql。

2 个答案:

答案 0 :(得分:1)

您可以通过将具有要覆盖的属性和值的数组传递给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;
        }
    ];
});

如果要传递自己的ID,闭包中的user_id值的原因是阻止创建另一个用户。

Overriding Attributes Documentation

答案 1 :(得分:1)

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

$factory->define(Book::class, function (Faker $faker) {
    return [
        'title'     => $faker->sentence,
        'author'    => $faker->name,
        'user_id'   => User::factory()->create()->id
    ];
});