Laravel 急切加载 phpunit 测试

Laravel eager loading phpunit testing

我正在尝试执行 GET 请求以通过 ID /GET 'film/{id}' 等检索特定电影

film_table

-- id

-- 描述

这是响应的一部分,如果我在电影模型中有多对多关系,如 film 模型

所示
public function languages(): BelongsToMany
{
    return $this->belongsToMany(
        'App\Models\Language',
        'film_languages',
        'film_id',
        'language_code'
    );
}

public function categories(): BelongsToMany
{
    return $this->belongsToMany(
        'App\Models\Category',
        'film_categories',
        'film_id',
        'category_id'
    );
}

有没有一种方法可以将这些表作为响应的一部分包括在内我在 Laravel 文档中遇到了一种叫做急切加载的东西,但不确定这是否涵盖了我需要的内容,我在下面有一个例子,但我'如果我在正确的轨道上,我会迷路吗?

FilmController

public function show(string $id): string
{
    /** @var Film  $film*/
    $film = film::findOrFail($id)
        ->with(
            'languages',
            'categories',
            )->get();

    return $film->toJson();

我正在尝试编写一个 PHPUnit 测试,以确保当通过 id returns iddescription 以及从多对多关系。

这是我开始的测试

FilmControllerTest

public function setUp(): void
{
    parent::setUp();

    $this->film = factory(Film::class)->create();

    $languages = factory(Language::class)->create();

    $categories = factory(Category::class)->create();
}

/**
 * @test
 */
public function it_should_get_film()
{
    $response = $this->json('GET', '/film/' . $this->film->id);

    $film= Film::findOrFail($this->film->id);

    $response->assertJson([
        'id' => $film->id,
        'description' => 'This is my favourite film'
    ]);
}

你能把这些关系包含到一个工厂中吗?

FilmFactory

    $factory->define(\App\Models\Film::class, function (Faker $faker) {
    return [
        'id' => $faker->uuid,
        'description' => $faker->paragraph
    ];
});

LanguagesFactory

  $factory->define(\App\Models\Language::class, function (Faker $faker){
    $langCode = $faker->languageCode;
    return [
        'code' => $langCode,
        'name' => $langCode,
    ];
});

CategoriesFactory

    $factory->define(\App\Models\Category::class, function (Faker $faker){

    return [
        'main' => $faker->text,
        'sub' => $faker->text,
    ];
});

我能得到一些帮助吗?我遇到了困难,一些帮助和例子会很棒 :) 谢谢!

您的方向非常正确。但是,存在一些语法错误。

这就是你抓取电影的方式,急切加载所需的关系和 return 它作为 JSON:

public function show($id)
{
    $film = Film::with(['languages', 'categories'])->findOrFail($id);

    return $film; // will automatically convert it to JSON
}

这就是您测试它的方式:

public function testShowFilm()
{
    $film = factory(Film::class)->create();

    $language = factory(Language::class)->create();

    $film->languages()->attach($language->id); // associate the film with the language

    $category = factory(Category::class)->create();

    $film->categories()->attach($category->id); // associate the film with the category

    $url = '/films/' . $film->id;

    $this->json('GET', $url)
        ->assertStatus(200)
        ->assertJsonPath(['id' => $film->id])
        ->assertJsonPath(['description' => $film->description])
        ->assertJsonPath(['languages.0.id' => $language->id])
        ->assertJsonPath(['categories.0.id' => $category->id]);
}

请注意,在您的场景中,您应该:

  • 3 模型 tables:电影、类别、语言;
  • 每个型号一个工厂table;
  • 2 关系 tables:film_categories 和 film_languages.

然后您可以使用上面示例中的 attach 方法将关系设置为测试的一部分,或者您可以使用工厂回调:

https://laravel.com/docs/6.x/database-testing#factory-callbacks