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 id
、description
以及从多对多关系。
这是我开始的测试
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
我正在尝试执行 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 id
、description
以及从多对多关系。
这是我开始的测试
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