2016-12-03 4 views
3

申し訳ありませんが、私の質問は非常に長いです。symfonyを使用してserviceTestでEntityManagerをモックする方法は?

KernelTestCaseを拡張したサービステストでentityManagerをモックする方法はありますか?

今、説明と私のテスト...私はSymfony3.2を使用しています

。私のアプリケーションは標準です。コントローラーがあり、WebTestCaseを使ってテストします。

私のコントローラはパラメータを検証し、サービス/マネージャを呼び出し、いくつかの変数を処理し、それらを表示するようにプッシュし、テストはかなり簡単にテストを延長します。WebTestCase

/** 
* Test New Game Action 
*/ 
public function testFooAction(){ 
    //We mock the Service 
    $fooService = $this 
     ->getMockBuilder(GameService::class) 
     ->disableOriginalConstructor() 
     ->getMock(); 
    $fooService->expects(self::once()) 
     ->method('barMethod') 
     ->willReturn($result); 

    //We create the client 
    $client = static::createClient(); 
    $container = $client->getContainer(); 

    //I put my mock here 
    $container->set('app.game-service', $fooService); 

    //I launch the request 
    $client->request('GET', '/foo'); 
    //I handle the response 
    $response = $client->getResponse(); 

    //I do some tests like this one 
    self::assertEquals(200, $response->getStatusCode()); 

} 

あなたが見ることができるように、私はでのエンティティ・マネージャを模擬するために問題を抱えている私のサービスのモック

//We create the client 
    $client = static::createClient(); 
    $container = $client->getContainer(); 

    //I put my mock here 
    $container->set('app.game-service', $fooService); 

を入れてサービスと、これらの行を使用しているため、私は、EntityManger呼び出すことはありません私のサービス。 My Controllerはテストされますが、My Serviceはテストされません。

単純なプロパティentityManagerで初期化されたコンストラクタです。ここでの問題は、

/** 
    * FooService constructor. 
    * @param EntityManager $entityManager 
    */ 
    public function __construct(EntityManager $entityManager) 
    { 
      $this->entityManager = $entityManager; 
    } 

私のサービスをテストするには...あなたはさらに見るように、このを保護している私の最初のコードです:完璧に動作testStart

<?php 
class FooServiceTest extends KernelTestCase 
{ 
    /** 
    * Foo Service. 
    * 
    * @var FooService 
    */ 
    private $fooService; 

    /** 
    * Prepares the environment before running each test. 
    */ 
    protected function setUp() 
    { 
     parent::setUp(); 

     self::bootKernel(); 
     $this->fooService = static::$kernel->getContainer() 
      ->get('app.foo-service') //HERE IS HOW I HANDLE MY SERVICE TO TEST IT 
     ; 

    } 

、いくつかのデータベースの相互作用があります。

私はテスト中にデータをロールバックできることを知っています。しかし、私はエンティティマネージャをモックしてcommitの方法の呼び出しを確認したいと思います。

私は私のセットアップではモックエンティティマネージャにこれを試してみてください。

protected function setUp() 
    { 
     parent::setUp(); 

     $entityManager = $this 
      ->getMockBuilder('Doctrine\ORM\EntityManager') 
      ->disableOriginalConstructor() 
      ->getMock(); 
     $entityManager 
      ->expects(once()) // I WANT EXACTLY ONE CALL TO COMMIT METHOD 
      ->method('commit') 
      ->willReturn(null); 

     self::bootKernel(); 
     $container = static::$kernel->getContainer(); 
     $container->set('doctrine.orm.entity_manager', $entityManager); // THIS LINE DOES NOTHING <======= 
     $this->gameService = static::$kernel->getContainer() 
      ->get('app.game-service') 
     ; 

THESコードは動作しません。モックは適所にない。私はまだ本当のentityManagerを持っています。私はそれがコンテナがすでに閉じられているからだと思う。それは野蛮人のように

を設定するためのナット便利ですか、私は公共

をEntityManagerのプロパティを変更し、私はそれを行う:それは完璧に動作

protected function setUp() 
    { 
     parent::setUp(); 

     $entityManagerMock = $this 
      ->getMockBuilder('Doctrine\ORM\EntityManager') 
      ->disableOriginalConstructor() 
      ->getMock(); 
     $entityManagerMock 
      ->expects(once()) // I WANT EXACTLY ONE CALL TO commit METHOD 
      ->method('commit') 
      ->willReturn(null); 

     self::bootKernel(); 
     $this->gameService = static::$kernel->getContainer() 
      ->get('app.game-service') 
     ; 
     $this->gameService->entityManager = entityManagerMock; 

。テストを実行できます。しかし、パブリックプロパティにentityManagerを持たせることは良い習慣ではありません。

私の質問は、サービステストでentityManagerをモックする方法ですか?

(申し訳ありませんが、私は英語に堪能ではないよ)あなたのコード内のすべての

+1

私は単体テスト(あなたの依存関係を模擬する場所、WebTestCaseのどちらかのテストを選択する必要があります。その場合は、テストデータベースを使用して、通常どおりにアプリケーションを使用する必要があります。私はまた、 "Barbarianのように、私はpublicにentityManagerプロパティを変更しました" – mickadoo

答えて

1

まず

$container->set('doctrine.orm.entity_manager'); // THIS LINE DOES NOTHING <======= 

私はあなたが二番目のパラメータを逃したと確信している:)

別のノート:ドンあなたが所有していないものを模倣しないでください。 今後はcomposer updateを実行し、EntityManagerのcommitにはオプションのisReallyCommitパラメータが含まれます。あなたのコードは壊れてしまいますが、テストは緑色であるため気づかないでしょう。私はそれは非常にありそうもないことを理解していますが、とにかくそれは単なる例です。私はここで良い練習が

    • には、エンティティマネージャといくつかのアダプタは
    • モックをincapsulated持つサービス単位でそのアダプタが何
    をからかっずに
  • 本当のデータベースに対して機能テストを使用して、アダプタをテストするテストだと思います

    またはユニットサービスをテストしますが、機能実際のデータベースとのやりとりでテストしてください

  • +0

    あなたの助けてくれてありがとう!私はあなたがこの文で何を意味するのか理解していません。エンティティマネージャを持つアダプタをいくつかカプセル化してください。私はあなたの答えを編集して、私に簡単な例を与えることができますか? –

    関連する問題