Symfony 2 testy funkcjonalne z wyśmiewanymi usługami

Mam kontroler, dla którego chciałbym stworzyć testy funkcjonalne. Ten kontroler wysyła żądania HTTP do zewnętrznego interfejsu API za pośrednictwemMyApiClient klasa. Muszę to wykpićMyApiClient klasa, więc mogę sprawdzić, jak mój kontroler odpowiada na dane odpowiedzi (np. co zrobi, jeśliMyApiClient klasa zwraca 500 odpowiedzi).

Nie mam problemów z tworzeniem wyśmiewanej wersjiMyApiClient class za pomocą standardowego PHPUnit mockbuilder: Mam problem z tym, aby mój kontroler używał tego obiektu do więcej niż jednego żądania.

Obecnie w teście wykonuję następujące czynności:

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;
    }
}

Wygląda na to, że pojemnik jest odbudowywany, gdy wykonywane jest drugie żądanie, powodującMyApiClient zostać ponownie utworzony. TheMyApiClient klasa jest skonfigurowana jako usługa za pomocą adnotacji (przy użyciu dodatkowego pakietu JMS DI) i wprowadzona do właściwości kontrolera za pomocą adnotacji.

Podzielę każde żądanie na własny test, aby obejść ten problem, jeśli będę mógł, ale niestety nie mogę: muszę wysłać żądanie do kontrolera za pomocą akcji GET, a następnie POST formularza, który przywraca. Chciałbym to zrobić z dwóch powodów:

1) Formularz korzysta z ochrony CSRF, więc jeśli POST prześlę bezpośrednio do formularza bez użycia przeszukiwacza do przesłania go, formularz nie przejdzie sprawdzenia CSRF.

2) Testowanie, czy formularz generuje poprawne żądanie POST po jego złożeniu, jest premią.

Czy ktoś ma jakieś sugestie, jak to zrobić?

EDYTOWAĆ:

Można to wyrazić w następującym teście jednostkowym, który nie zależy od żadnego z moich kodów, więc może być jaśniejszy:

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.
}

Ten test kończy się niepowodzeniem, nawet jeśli zadzwonię$client->getContainer()->set($keyName, new \stdClass()); bezpośrednio przed drugim wywołaniemrequest()

questionAnswers(6)

yourAnswerToTheQuestion