Как в Yii2 Codeception создать моки для внешнего API в тестах REST API?

Каков наилучший подход к мокированию сторонних API во время написания тестов, чтобы избежать случайных вызовов и увеличить стабильность во время выполнения тестов?
  • 3 апреля 2024 г. 11:09
Ответы на вопрос 2
Для создания моков в Yii2 Codeception для внешнего API в тестах REST API можно воспользоваться библиотекой Guzzle Mock Handler. Эта библиотека позволяет эмулировать ответы от внешнего API и управлять тестовыми сценариями.

Прежде всего, необходимо установить Guzzle Mock Handler в проект:

```
composer require --dev phpunit/phpunit guzzlehttp/guzzle guzzlehttp/promises guzzlehttp/psr7 guzzlehttp/guzzle
```

Затем создайте мок запрос со своими желаемыми данными для автоматического имитирования ответа в тестах REST API:

```php
use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;

$mock = new MockHandler([
    new Response(200, ['X-Foo' => 'Bar'], 'Hello, World')
]);

$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
```

В вашем тестовом сценарии вы можете использовать созданный мок для отправки запросов к внешнему API:

```php
use GuzzleHttp\Exception\RequestException;

try {
    $response = $client->request('GET', 'https://api.example.com');
    $statusCode = $response->getStatusCode();
    $body = $response->getBody()->getContents();
} catch (RequestException $e) {
    $response = $e->getResponse();
    $statusCode = $response->getStatusCode();
    $body = $response->getBody()->getContents();
}

// Проверки результатов запроса
$this->assertEquals(200, $statusCode);
$this->assertEquals('Hello, World', $body);
```

Таким образом, вы можете эффективно создавать моки для внешнего API в тестах REST API с помощью Guzzle Mock Handler, что позволяет избежать случайных вызовов и обеспечивает стабильность выполнения тестов.
Простой вариант (костыли): 

Добавить в функциях, которые ожидают ответ от внешних сервисов, исключения для тестов
if (YII_ENV_TEST) {
    return true;
}


Правильный вариант :

Зарегистрировать сервис внешних обращений в конфиге, в коде пользоваться только сервисом из контейнера Yii::$app->apiService

Cоздать загрулшку и зарегистрировать ее в качестве этого сервиса в тестовом конфиге
# config/test.php

$config =  yii\helpers\ArrayHelper::merge(
    require(__DIR__ . '/web.php'),
    [
        'id' => 'app-tests',
        'components' => [
            'apiService' => [
                'class' => 'App\Fake\ApiService',
            ],
        ],
    ],
);
return $config;

Тестовый конфиг использовать в настройках модуля Codeception
# tests/integration.suite.yml

class_name: IntegrationTester
modules:
    enabled:
      - Asserts
      - Yii2:
            part: [orm, email, fixtures]
            configFile: 'config/test.php'
Похожие вопросы