1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Laravel]assertableJsonでJson形式のままテストする

Posted at

はじめに

Laravelによる初めてのAPIのテストコードを書いていた

あらかた完成したタイミングで、ふと同僚にコードを見てもらった時に

「Jsonのままテストできるよ」

と指摘され、調べたときのメモ

環境

  • PHP 8.0.5
  • Laravel 8.5.0

テスト前の準備とテスト内容

Model

まずはApp/Models/User.phpにてユーザーに紐づく注文を取得できるようにリレーションを張る

/**
 * ユーザーに紐づく注文の取得.
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function orders()
{
    return $this->hasMany(Order::class);
}

Controller

Controllerのindexメソッドで返ってくるAPIのJSONデータをテスト

/**
 * ユーザーに紐づく注文の取得.
 *
 * @return \Illuminate\Database\Eloquent\Relations\HasMany
 */
public function index()
{
		// ログインユーザーの注文の取得
    $orders = User::findOrFail(Auth::id())
        ->orders()
        ->get();

    return response()->json([
        'success' => true,
        'orders' => $orders->map(function ($orders) {
            return [
                'uuid' => $orders->uuid,
                'name' => $orders->name,
                'phone_number' => $orders->phone_number,
                'updated_at' => $orders->updated_at->format('Y-m-d H:i:s.u'),
            ];
        }),
    ]);
}

以下のJsonデータが返ってくるAPIのテストをする

ordersは多重配列構造。

返ってくるJsooデータ

{
    success : true,
    orders : 
    [
        uuid: ...
		name: ...
		phone_number: ...
		updated_at: ...
    ],
    [
        uuid: ...
		name: ...
		phone_number: ...
		updated_at: ...
    ],
	...
}

当初のテストコード

同僚に初めて見せたテストコードがこちら。

/**
 * ユーザーに紐づく注文の取得のテスト.
 *
 * @void
 */
protected function testIndex()
{
	// ユーザー、注文情報の取得
	$user = User::findOrFail(1); // ここは仮でIDおいてます。
    $orders = $user->orders;

	// API呼び出し(routeの名前は仮)
    $response = $this->actingAs($user)->getJson(route('api.orders.index'));

	// jsonデータを配列に変換
    $contentArray = json_decode((string) $response->getContent(), true);
    $contentArrayCount = count($contentArray['orders']);

	// 以下ひたすらテスト
	$this->assertCount(2, $contentArrayCount);
	$this->assertIsBool($contentArray['success']);
	$this->assertIsArray($contentArray['orders'])
	$this->assertSame('true', $contentArray['success']);
	...
	...
}

API呼び出し後に取得値をJsonから配列に置き換えて、PHPUnitにあるメソッドを使ってテストを実行している

どうやってやるの?

では、Jsonのままテストをするにはどうするのさ、と調べるとLaravelドキュメントのHTTPテストを見て即解決した。

assertJsonCountだとかassertJsonといういかにも、なメソッドを発見。

さらにassertJsonとassertableJsonを使うと、今回のような多重配列のJsonでも柔軟なテストが可能であった。

assertJsonについて実用的な書き方は以下記事で書いていますので、初めてAPIテストコードを書く方のお役に立てると嬉しいです。

修正後のテストコード

/**
 * ユーザーに紐づく注文の取得のテスト.
 *
 * @void
 */
protected function testIndex()
{
	// ユーザー、注文情報の取得
	$user = User::findOrFail(1); // ここは仮でIDおいてます。
    $orders = $user->orders;

	// API呼び出し(routeの名前は仮)
    $response = $this->actingAs($user)->getJson(route('api.orders.index'));

	// 以下ひたすらテスト
	$this->assertJsonCount(2);
	$response->assertJson(function (AssertableJson $json) use ($contentArrayCount) {
	    $json->whereAllType([
	          'success' => 'boolean',
	          'orders' => 'array',
	    ]);
		$json->where('success', true);
	}, true);
	...
	...
}

Jsonのままテストができるので、配列に置き換える必要がなくなった。

おわりに

初めての作業であれば、ちゃんと公式ドキュメントは読もう。

得るものは大きかった。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?