機能テストを作成したいコントローラーがあります。MyApiClient
このコントローラーは、クラスを介して外部APIにHTTPリクエストを送信します。このクラスをモックアウトする必要があるので、コントローラーが特定の応答に対してどのように応答するかをテストできます(たとえば、クラスが500応答を返したMyApiClient
場合はどうなりますか)。MyApiClient
標準のPHPUnitモックビルダーを使用してクラスのモックバージョンを作成することに問題はありません。私が抱えているMyApiClient
問題は、コントローラーがこのオブジェクトを複数のリクエストに使用できるようにすることです。
私は現在、テストで次のことを行っています。
class ApplicationControllerTest extends WebTestCase
{
public function testSomething()
{
$client = static::createClient();
$apiClient = $this->getMockMyApiClient();
$client->getContainer()->set('myapiclient', $apiClient);
$client->request('GET', '/my/url/here');
// Some assertions: Mocked API client returns 500 as expected.
$client->request('GET', '/my/url/here');
// Some assertions: Mocked API client is not used: Actual MyApiClient instance is being used instead.
}
protected function getMockMyApiClient()
{
$client = $this->getMockBuilder('Namespace\Of\MyApiClient')
->setMethods(array('doSomething'))
->getMock();
$client->expects($this->any())
->method('doSomething')
->will($this->returnValue(500));
return $apiClient;
}
}
2番目のリクエストが行われたときにコンテナが再構築されているように見え、がMyApiClient
再びインスタンス化されます。このMyApiClient
クラスは、アノテーションを介して(JMS DI Extra Bundleを使用して)サービスになるように構成され、アノテーションを介してコントローラーのプロパティに挿入されます。
可能であれば、これを回避するために各リクエストを独自のテストに分割しますが、残念ながらできません。GETアクションを介してコントローラーにリクエストを送信し、返されるフォームをPOSTする必要があります。私は2つの理由でこれをしたいと思います:
1)フォームはCSRF保護を使用しているため、クローラーを使用せずにフォームに直接POSTすると、フォームはCSRFチェックに失敗します。
2)フォームが送信されたときに正しいPOSTリクエストを生成することをテストすることはボーナスです。
誰かがこれを行う方法について何か提案がありますか?
編集:
これは、私のコードのいずれにも依存しない次の単体テストで表現できるため、より明確になる可能性があります。
public function testAMockServiceCanBeAccessedByMultipleRequests()
{
$client = static::createClient();
// Set the container to contain an instance of stdClass at key 'testing123'.
$keyName = 'testing123';
$client->getContainer()->set($keyName, new \stdClass());
// Check our object is still set on the container.
$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName))); // Passes.
$client->request('GET', '/any/url/');
$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName))); // Passes.
$client->request('GET', '/any/url/');
$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName))); // Fails.
}
$client->getContainer()->set($keyName, new \stdClass());
このテストは、 2回目の呼び出しの直前に呼び出しても失敗します。request()