LaravelのAPIテストを簡単に書いて実行しよう！


#目的
APIのテストケースを簡単に実装したい（なるだけ少ないコードで！）

今回できることは get, post, putの実行とレスポンスが正常かをテストするコードが簡単に実装できるようになります。

# 基底クラス（ApiTestBase.php）を作る

`tests/Feature`以下に下記ファイルを作ります。

```ApiTestBase.php
<?php

namespace Tests\Feature;

use Tests\TestCase;

class ApiTestBase extends TestCase
{
  protected $get_api_url = "/api/{your route}";
  protected $update_api_url = "/api/{your route}";
  protected $insert_api_url = "/api/{your route}";

  protected $doGetTest = true;
  protected $doInsertTest = true;
  protected $doUpdateTest = true;

  public function testGet()
  {
    if (!$this->doGetTest) {
      $this->assertTrue(true);
      return;
    }
    echo "[start] get:".$this->get_api_url."\n";

    $this->withoutMiddleware();

    $user = factory(\App\User::class)->create();
    $this->actingAs($user);

    $response = $this->get($this->get_api_url);
    $response->assertSuccessful();

    $data = $response->decodeResponseJson();
    // dd($data);
    self::doAssertResponse($data);
  }

  public function testInsert()
  {
    if (!$this->doInsertTest) {
      $this->assertTrue(true);
      return;
    }
    echo "[start] post:".$this->insert_api_url."\n";

    $this->withoutMiddleware();

    $user = factory(\App\User::class)->create();
    $this->actingAs($user);

    $param = $this->createInsertParam();
    $response = $this->post($this->insert_api_url, $param);
    // \Log::info($response->decodeResponseJson());
    $response->assertSuccessful();
  }

  public function testUpdate()
  {
    if (!$this->doUpdateTest) {
      $this->assertTrue(true);
      return;
    }
    echo "[start] update:".$this->update_api_url."\n";

    $this->withoutMiddleware();

    $user = factory(\App\User::class)->create();
    $this->actingAs($user);

    $param = $this->createUpdateParam();

    $response = $this->put($this->update_api_url, $param);
    // \Log::info($response->decodeResponseJson());
    $response->assertSuccessful();
  }

  /**
   * Responseの中身をチェック
   */
  protected function doAssertResponse($data)
  {
    $this->assertTrue(0 < count($data));
  }

  protected function createInsertParam()
  {
    //
  }

  protected function createUpdateParam()
  {
    //
  }
}
```

# ApiTestBaseを継承したテストクラスを実装する

下記のように実装しましょう。
apiのルートを書いて、`createInsertParam()` ,`createUpdateParam()`にはcreate/update対象のRequest内容を書きます。


```PostApiControllerTest.php
<?php

namespace Tests\Feature;

class PostApiControllerTest extends ApiTestBase
{
    protected $get_api_url = "/api/posts";
    protected $update_api_url = "/api/posts/1";
    protected $insert_api_url = "/api/posts";

    protected function createInsertParam()
    {
      $param = [
        'userId' => 100,
        'body' => 'note'
      ];
      return $param;
    }
  
    protected function createUpdateParam()
    {
      $param = [
        'id' => '1'
        'body' => 'note[update]'
      ];
      return $param;
    }
}
```

#テスト実行
コマンドで上記の実行ファイルをtestしてみましょう。

```console
vendor/bin/phpunit tests/Feature/PostApiControllerTest.php
```


#実行したくないテストがある場合

`$doGetTest`, `$doInsertTest`, `$doUpdateTest`それぞれ除外したいテストのフラグを **false** にすればテスト実行されません。
（実際は強制的にassetTrueにしてreturnしてる）

```PostApiControllerTest.php
<?php

namespace Tests\Feature;

class PostApiControllerTest extends ApiTestBase
{
    protected $get_api_url = "/api/posts";
    protected $insert_api_url = "/api/posts";

    // protected $doGetTest = true; *defaultはtrue
    // protected $doInsertTest = true; *defaultはtrue
    protected $doUpdateTest = false; //テスト除外
```

#responseの中身をチェックする

`doAssertResponse`をoverrideして好きな処理を実装してください。
（getの時だけ対応してるのでinsert, updateで必要な場合は個別実装）

```php
  /**
   * Responseの中身をチェック
   */
  protected function doAssertResponse($data)
  {
    $this->assertTrue(0 < count($data));
  }
```

Testクラスの生成も独自コマンドで自動生成したらさらに楽になります。

それではまた！