9

コントローラーアクションでデータベースの挿入/更新/削除を使用して、Symony2 で非常に単純な REST コントローラーを作成しました。

実稼働データベースを汚染することなく、これらのコントローラー アクションの単体/統合テストを作成する良い方法はありますか? さまざまな環境で作業する必要がありますか? または、フレームワーク ベンダーから提案された方法はありますか?

電流コントローラーの例:

public function postAction()
{
    $json = $this->getRequest()->getContent();
    $params = json_decode($json);
    $name = $params->name;
    $description = $params->description;

    $sandbox = new Sandbox();
    $sandbox->setName($name);
    $sandbox->setDescription($description);
    $em = $this->getDoctrine()->getManager();
    $em->persist($sandbox);
    $em->flush();

    $response = new Response('/sandbox/'.$sandbox->getId());
    $response->setStatusCode(201);
    return $response;
}

現在のテスト例:

class SandboxControllerTest extends WebTestCase
{

    public function testRest()
    {
        $client = static::createClient();

        $crawler = $client->request('POST', '/service/sandbox', array(), array(), array(), json_encode(array('name' => 'TestMe', 'description' => 'TestDesc')));

        $this->assertEquals(
                201, $client->getResponse()->getStatusCode()
        );
    }
}
4

3 に答える 3

18

私の意見では、テストでデータベースを変更することは絶対に避けるべきです。

これを達成するための私のお気に入りの方法は、テスト クライアント内にエンティティ マネージャー モックを挿入することです。例えば:

public function testRest()
{
    // create entity manager mock
    $entityManagerMock = $this->getMockBuilder('Doctrine\ORM\EntityManager')
        ->setMethods(array('persist', 'flush'))
        ->disableOriginalConstructor()
        ->getMock();

    // now you can get some assertions if you want, eg.:
    $entityManagerMock->expects($this->once())
        ->method('flush');

    // next you need inject your mocked em into client's service container
    $client = static::createClient();
    $client->getContainer()->set('doctrine.orm.default_entity_manager', $entityManagerMock);

    // then you just do testing as usual
    $crawler = $client->request('POST', '/service/sandbox', array(), array(), array(), json_encode(array('name' => 'TestMe', 'description' => 'TestDesc')));

    $this->assertEquals(
            201, $client->getResponse()->getStatusCode()
    );
}

このソリューションで知っておくべきことの 1 つは、各リクエストの前にモック サービスを挿入する必要があることです。これは、クライアントが各要求の間にカーネルを再起動するためです (つまり、コンテナーも再構築されることを意味します)。

編集:

コントローラーのテストでの私の GET アプローチは、db からデータを取得するたびにスタブ化するためにエンティティ リポジトリなどをモックできるというものですが、それは大変な作業であり、あまり快適ではないため、この場合を好みます (話す場合のみを意味します)。コントローラーのテストについて)実際にdbから実際のデータを取得します。実際のデータとは、ドクトリン フィクスチャで作成されたデータを意味します。データベースを変更しない限り、フィクスチャに依存できます。

しかし、db 内のデータの変更 (POST/PUT/DELETE メソッド) について話している場合は、常にモックを使用します。em モックを使用し、「perist」および「flush」メソッドに適切な期待値を設定すると、データベースを変更することなく、実際にデータが正しく作成/更新/削除されることを確認できます。

于 2013-01-19T12:56:33.357 に答える
4

これが私がすることです

テスト クラスに $kernel 静的変数を追加し、テスト モードでカーネルをロードする関数を作成します。

protected static $kernel;
protected static $container;

public static function setUpBeforeClass()
{
    self::$kernel = new \AppKernel('test', true);
    self::$kernel->boot();

    self::$container = self::$kernel->getContainer();
}

そして、テスト関数の最初の行として、呼び出しますself:setUpBeforeClass()

これにより、symfony は config_test.yml 構成ファイルをロードし、そこで別のデータベース接続を定義できます。

于 2013-01-19T12:58:54.217 に答える