Cake PHP 3 - Mock HTTP \ Client () в интеграционном тесте - PullRequest
0 голосов
/ 12 января 2020

Я использую Cake\Http\Client ( book ) для доступа к некоторым внешним приложениям. В моих модульных тестах я на самом деле не могу использовать эти сервисы.

Так как же смоделировать Http-клиента в тесте интеграции контроллера? Было бы неплохо, если бы я мог, например, прописать точный ответ, даже не выполняя фактический HTTP-запрос.

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

1 Ответ

0 голосов
/ 22 января 2020

Я почти уверен, что не существует встроенного решения для насмешки над объектом Http \ Client, учитывая, что я не могу найти ничего на страницах документации или API.

Поэтому вместо этого я использовал PHP HTTP-клиент, Жрать . Guzzle разрешает имитацию, ставя в очередь предопределенные ответы, именно то, что я хотел.

Однако плавная интеграция с Cake PHP не была тривиальной, поскольку конструктор клиента Guzzle требует прохождения стека макетов. Я решил это, создав клиентскую фабрику:

<?php

namespace App\Guzzle;

use GuzzleHttp\Client;

/**
 * Guzzle factory
 * 
 * Created to make guzzle clients mockable
 */
class GuzzleFactory
{
    static $options = [];

    /**
     * Create new client
     * 
     * @return \GuzzleHttp\Client
     */
    static function create()
    {
        return new Client(self::$options);
    }

    /**
     * Set handler stack in global options for new clients
     * 
     * @param \GuzzleHttp\HandlerStack $handlerStack
     */
    static function setTest($handlerStack)
    {
        self::$options['handler'] = $handlerStack;
    }

    /**
     * Set options array to default
     */
    static function reset()
    {
        self::$options = [];
    }
}

Затем в тестах моего контроллера у меня есть функция:

/**
 * Set Guzzle mock responses
 * 
 * @param array $list
 */
public function setGuzzleResponses($list)
{
    if (!is_array($list))
    {
        $list = [$list];
    }
    $mock = new MockHandler($list);
    $handlerStack = HandlerStack::create($mock);
    GuzzleFactory::setTest($handlerStack);
}

Такая, что внутри теста я могу вызвать:

    // ...
    $this->setGuzzleResponses([
        new Response(200, [], json_encode($response))
    ]);
    $this->get("/page/index"); // This request will make an HTTP call
    // ...

Также см. http://docs.guzzlephp.org/en/stable/testing.html

...