CodeIgniter4のREST APIのテストを書く
この記事は CodeIgniter Advent Calendar 2020 - Qiita の21日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。
今日は昨日作成した CodeIgniter4 の REST API のテストコードを作成してみます。
CodeIgniter4のフィーチャーテスト も参考にしてください。
動作確認環境
- CodeIgniter 4.0.5 開発版
- PHP 7.4.13
- MySQL 5.7.32
- macOS 10.15.7
シーダーの準備
News テーブルの状態を同一にするシーダーを以下のように作成します。
tests/_support/Database/Seeds/NewsSeeder.php
<?php
namespace Tests\Support\Database\Seeds;
use CodeIgniter\Database\Seeder;
class NewsSeeder extends Seeder
{
public function run()
{
$table = 'news';
$this->db->table($table)->truncate();
$data = [
[
'title' => 'Elvis sighted',
'slug' => 'elvis-sighted',
'body' => 'Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app.',
],
];
$this->db->table($table)->insertBatch($data);
}
}
まず、CodeIgniter4 のメソッドを使い、テーブルを truncate します。
$this->db->table($table)->truncate();
そして、レコードを 1件挿入します。
$this->db->table($table)->insertBatch($data);
このシーダーを実行すれば、テーブルの状態が同じになります。
フィーチャーテストの作成
テストファイルの作成
tests/feature/Api/
フォルダを追加して、NewsTest.php
を作成します。
tests/feature/Api/NewsTest.php
<?php
namespace Tests\Feature\Api;
use Tests\Support\Database\Seeds\NewsSeeder;
use CodeIgniter\Test\FeatureTestCase;
class NewsTest extends FeatureTestCase
{
protected $refresh = false;
protected $namespace = 'App';
}
App\Database\Migrations
以下のマイグレーションファイルを使い、テストごとにデータベースをリフレッシュする(バージョン 0 まで戻し再度最新バージョンまでマイグレーションする)ことはしないように設定しています。
シーダーを実行するメソッドの追加
現状、CodeIgniter4 の FeatureTestCase には自動的にシーダーを 1回だけ実行する方法がありません。
(2021-02-23 追記) CodeIgniter 4.0.5以降にはマイグレーションを実行しない設定やマイグレーションやシーダーを一度だけ実行する設定が追加されました。
そこで、シーダーを実行するメソッドをテストファイルに追加します。
private function runSeeder()
{
$this->seeder->setPath(rtrim($this->basePath, '/') . '/Seeds');
$this->seed(NewsSeeder::class);
}
GET api/news
全ての記事を取得する API のテストです。
最初のテストです。ここでシーダーを実行します。
public function test_get_api_news()
{
$this->runSeeder();
$result = $this->get('api/news');
$result->assertStatus(200);
$result->assertJSONFragment(
[
'news' => [
['title' => 'Elvis sighted'],
]
]
);
$json = $result->getJSON();
$this->assertJsonStringEqualsJsonString(
'{
"status": 200,
"error": null,
"news": [
{
"id": "1",
"title": "Elvis sighted",
"slug": "elvis-sighted",
"body": "Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app."
}
]
}',
$json
);
}
CodeIgniter4 の $result->assertJSONFragment()
は、JSON にデータが含まれるかどうか確認するメソッドです。
CodeIgniter4 の $result->getJSON()
で、レスポンスの JSON 文字列を取得できます。
GET api/news/{id}
指定の記事を取得する API のテストです。
public function test_get_api_news_id()
{
$result = $this->get('api/news/1');
$result->assertStatus(200);
$result->assertJSONFragment([
'news' => [
'title' => 'Elvis sighted',
],
]);
}
POST api/news
記事を新規作成する API のテストです。
public function test_post_api_news()
{
$params = [
'title' => 'New news',
'body' => 'This is a new news.',
];
$result = $this->post('api/news', $params);
$result->assertStatus(201);
$this->seeInDatabase('news', [
'title' => 'New news',
]);
}
これで id=2 のニュースが作成されます。
CodeIgniter4 の $this->seeInDatabase()
メソッドで、含まれるデータを確認します。
PUT api/news/{id}
記事を更新する API のテストです。
public function test_put_api_news_id()
{
$params = [
'title' => 'Updated new news',
'body' => 'This is an updated new news.',
];
$result = $this->withBody(http_build_query($params))
->put('api/news/2', $params);
$result->assertStatus(200);
$this->dontSeeInDatabase('news', [
'title' => 'New news',
]);
$this->seeInDatabase('news', [
'title' => 'Updated new news',
]);
}
CodeIgniter4 の $this->dontSeeInDatabase()
メソッドで、データベースに含まれないデータを確認します。
DELETE api/news/{id}
記事を削除する API のテストです。
public function test_delete_api_news_id()
{
$result = $this->delete('api/news/2');
$result->assertStatus(200);
$this->dontSeeInDatabase('news', [
'title' => 'Updated new news',
]);
}
テストの実行
テストを実行します。
$ vendor/bin/phpunit tests/feature/Api/NewsTest.php
PHPUnit 8.5.13 by Sebastian Bergmann and contributors.
Error: XDEBUG_MODE=coverage or xdebug.mode=coverage has to be set
..... 5 / 5 (100%)
Time: 510 ms, Memory: 10.00 MB
OK (5 tests, 14 assertions)
通りました!
この記事は CodeIgniter Advent Calendar 2020 - Qiita の21日目です。まだ、空きがありますので、興味のある方は気軽に参加してください。
参考
Date: 2020/12/21