2017-11-22 4 views
0

DBにCRUD操作を行い、DBから結果を返すREST APIを1つ作成しました。さて、これは私の以下のコードである:ここではPHPUnit:CRUD操作を行うREST APIをテストする方法を改善する

class CreateRecords 
{ 
    public function createEntities($details) 
    { 
     if (trim($details['username']) == "") { 
      $this->result = "Username is empty."; 
     } else { 
      $this->result = create_record($userDetails); 
     }  
     return $this->result; 
    } 
} 

、この上記のコードでは、create_recordは、検証パーツを行い、DBに詳細を挿入して、新しく作成されたレコードのIDを返す関数です。

さて、現在、私のテストケースはこのようなものです:だから

class TestCreateRecords 
{ 
    public function setUp() 
    { 
     $this->client = new GuzzleHttp\Client([ 
       'base_uri' => 'http://localhost/test/' 
      ]); 
    } 

    public function testCreateEntitiesAPI() 
    {   
     $response = $this->client->post('service.php', [ 
      'json' => [ 
       'username' => '[email protected]', 
       'user_password' => 'test', 
       'first_name' => 'Test', 
       'last_name' => 'test', 
       'email1' => '[email protected]' 
      ] 
     ]); 

     $actual_response = json_decode($response->getBody(), true); 

     $this->assertArrayHasKey("id", $actual_response, 'Un-successful.'); 
    } 
} 

、私はいくつかの本についての問合せがあります。私のメインクラスファイルで

  1. を、create_record機能は、挿入する前にusernameを検証しますDBの詳細。 usernameがすでに利用可能かどうかをチェックします。可能であれば、レコードを作成せず、応答をAlready Availableとして送信します。利用できない場合は、レコードを作成し、新しく作成した一意のIDを送信します。

    ここでは、usernameがすでにDBで利用可能で、DBで利用できないというシナリオを両方ともテストしたいと考えています。さて、上記のテストケースでは、テストを実行する前に毎回変更する必要があるため、シナリオをテストできます。usernameは既にDBで利用できません。そして、それは私には不合理なようです。

    私が知りたいのは、私がこれを達成できる他の方法はありますか?

  2. 誰かが、create_recordメソッドを模擬してAPIをテストし、create_recordメソッド自体をテストするための別のテストケースを書くことを勧めました。しかし、私のアプリケーションのMVCフレームワークによれば、私にとっては今のところ不可能と思われます。 create_recordメソッドでは、呼び出されているメソッドが数多くあり、これらのメソッドは他のメソッドをほとんど呼びません。もう一度、私はそれらの数十のメソッドを模擬し、それらのためのテストケースを書く必要があります。

    私たちにとっては時間と労力がかかります。だから私はどんな方法も模擬しないようにし、一つのテストケースでAPIの流れ全体をテストすることに決めました。

    私は知っている、それは良いアプローチですか?そして、それの副作用は何でしょうか?

答えて

1

誰でも嘲笑してみることをお勧めします。より多くのテストを開始したいのは素晴らしいことですが、アプリケーションアーキテクチャーで問題が発生することがよくあります。

単体テストは理想的には単一のクラスまたは関数をテストする必要があります。すべての関数がデータベース挿入まで他の関数を呼び出しているのであれば、それはエンドツーエンドのテストです。これらを持つことは問題ありませんが、さまざまなケースをテストしたい場合(ユーザー名が存在するため検証に失敗した場合)、エンドツーエンドのテストですべてのエッジケースをテストするとが遅いです。

あなたはすでにCreateRecordsクラスを持っています。これはservice.phpクラスで使用されていますか?あなたが何らかの依存性注入を使用しているのであれば、コントローラ内のクラスをモックすることができます(私はservice.phpと推測しています)。この方法で、APIコードとは別にサービスをテストできます。次に例を示します。

/** 
* Controller action 
*/ 
function myAction() { 
    if ($this->isAdmin()) { 
    throw new \Exception('You need to be an admin'); 
    } 

    $this->userService->create($_POST); 
} 

/** 
* Service containing actions related to users 
*/ 
class UserService { 

    /** 
    * @var UserValidator 
    */ 
    protected $validator; 

    /** 
    * @var RecordSaver 
    */ 
    protected $recordSaver; 

    /** 
    * @param UserValidator $validator 
    * @param RecordSaver $recordSaver 
    */ 
    public function __construct(
    UserValidator $validator, 
    RecordSaver $recordSaver 
) { 
    $this->validator = $validator; 
    $this->recordSaver = $recordSaver; 
    } 

    /** 
    * @param $params 
    * @return array 
    */ 
    public function create($params) { 
    $this->validator->validate($params); 

    return $this->recordSaver->save($params); 
    } 
} 

/** 
* Validation of new users/or updating existing 
*/ 
class UserValidator { 
    /** 
    * @param array $params 
    * @throws Exception 
    */ 
    public function validate($params) { 
    if (!isset($params['username'])) { 
     throw new \Exception('Username must be set'); 
    } 
    } 
} 

/** 
* Wrapper for database calls 
*/ 
class RecordSaver { 
    /** 
    * @param array $params 
    * @return array 
    */ 
    public function save($params) { 
    return create_record($params); 
    } 
} 

次に、各レイヤーのみをテストするテストを作成できます。

  • APIが例外をスローする場合は、ユーザーの検証のためのさまざまなユニットテストの多くは
  • はUserServiceの中にユーザー作成のためのいくつかのテストは、(バリデータとレコードをからかっていない管理者
  • かどうかを確認するテスト保護者)
+0

ありがとうmickadoo。私は、このようなシナリオでは、メソッドの嘲笑が良い選択であることを知っています。あなたが与えた例はかなり良いです。しかし、私の実際の実際のコードは非常に圧倒的です、あなたが上記のようにそれを整理することはかなり難しいほど複雑です。また、私のポストで私によって提起された最初のクエリのあなたのテイクを知っているかもしれませんか?このAPIをテストするために使用しているデータについて –

+0

ええ、私は想像することができます。継承したコードでこれを実装するのは非常に難しいです。あなたの最初の質問では、私の例のように冗談を使うことができたら、バリデーターは重複したレコードを返すモックデータベースを持っていると思います。レコードがすでに存在する場合、バリデータが例外を正しくスローすることをテストするだけです。冗談なしでは、重複したレコードを 'setUp'に挿入し、テストの' tearDown'メソッドでそれを削除することだけが考えられます。 – mickadoo

関連する問題