codeception symfony functional Функциональные тесты, Получение клиента (client)- заметки, mock

Наброски того, как можно организовать функциональное тестирование API без браузера/сервера

Проверялось на: Symfony 6, Symfony 7, Codeception 5

Получение клиента

См. отдельную заметку о получении клиента

Использование клиента - отправка запросов

Используя клиент можно авторизоваться напр. так (в т.ч. получить куку):

    protected function createClient(UserAuthData $userCred)
    {
        $client = $this->getUnauthedClient();
        if (!empty($userCred->username) && !empty($userCred->password)) {
            $client->request(
                'POST',
                "/api/" . $this->getApiVersion() . "/login",
                [],
                [],
                ['CONTENT_TYPE' => 'application/json'],
                json_encode($userCred)
            );

            if ($client->getResponse()->getStatusCode() !== Response::HTTP_OK) {
                throw new AccessDeniedHttpException('C авторизацией что-то пошло не так');
            }
        } else {
            throw new \Exception('User data format not valid!');
        }

        $this->functionalTester->assertEquals(200, $client->getResponse()->getStatusCode());

        
        return $client;
    }

-- тут мы шлем "запрос" к методу авторизации (ниже см. как обойтись без этого, используя программную авторизацию, если требуется)

В свою очередь "создание клиента" (по сути тут скорее "создание авторизованного клиента", т.к. базовый объект клиентам мы извлекаем из ядра условно называя его "неавторизованным" в коде выше) можно использовать для авторизации под конкретным юзером:

    /**
     * Авторизация под админом
     * 
     * @param FunctionalTester $I
     */
    protected function authAsAdmin(FunctionalTester $I)
    {
        $this->client = $this->createClient($this->getAdminAuthData());
    }

Далее, как обычно в кодэсэпшн можно использовать зависимости типа before, чтобы сначала авторизоваться, а потом, напр. запросить данные пользователя:

   /**
     * @before authAsAdmin
     */
    public function getAdminInfo(FunctionalTester $I)
    {
        $client = $this->client;
        $client->request(
            'GET',
            '/api/' . $this->getApiVersion() . '/user_info',
            [],
            [],
            [],
        );

        $rsContent = json_decode($client->getResponse()->getContent(), true);


        $I->assertEquals(200, $client->getResponse()->getStatusCode());
        $I->assertArrayHasKey('roles', $rsContent);
        $I->assertContains('ROLE_ADMIN', $rsContent['roles']);
    }

Как подменить объект пользователя (полезно при изоляции авторизации, напр. в микросервисе)

См. в отдельной заметке о подмене авторизации, программной авторизации

Видео-материалы

  • О функциональных тестах в целом: https://youtu.be/1vKDqzuMVeU
  • Как организовать функциональные тесты на Symfony с использованием Codeception https://youtu.be/RN2_1x__-bQ
  • Подмена пользователя, авторизация с указанной ролью (в т.ч. для несуществующего пользователя): https://youtu.be/j4-ttbmaOFM

Источники