Я наткнулся на этот вопрос, когда пытался самостоятельно протестировать класс с помощью cURL. Я принял совет Дэвида Харкнесса близко к сердцу и создал интерфейс для cURL. Тем не менее, функциональность заглушки / макета, предоставляемая PHPUnit, в моем случае была недостаточной, поэтому я добавил собственную реализацию заглушки интерфейса и поместил все это на GitHub. И поскольку этот вопрос довольно рано появляется в Google при поиске этой проблемы, я подумал, что опубликую его здесь, чтобы другие могли сэкономить усилия.
Вот оно.
Вики-репозиторий содержит довольно подробную документацию о возможностях заглушки, но здесь они вкратце.
Интерфейс представляет собой отображение 1: 1 функций cURL в PHP, что позволяет очень легко начать использовать интерфейс (просто вручите свой ClassUnderTest
экземпляр, реализующий SAI_CurlInterface
, а затем вызовите все функции cURL, как и раньше, но как методы в этом случае). Класс SAI_Curl
реализует этот интерфейс путем простого делегирования в cURL. Теперь, если вы хотите проверить ClassUnderTest
, вы можете дать ему экземпляр SAI_CurlStub
.
Заглушка в основном устраняет проблему, заключающуюся в том, что макеты и заглушки PHPUnit не могут возвращать фиктивные данные в зависимости от предыдущих вызовов функций (но именно так на самом деле работает cURL - вы устанавливаете свои параметры, и ответ, код ошибки и информация cURL зависят от этих опции). Итак, вот короткий пример, показывающий эти возможности для ответов (коды ошибок и информацию о cURL см. В вики).
public function testGetData()
{
$curl = new SAI_CurlStub();
// Set up the CurlStub
$defaultOptions = array(
CURLOPT_URL => 'http://www.myserver.com'
);
$chromeOptions = array(
CURLOPT_URL => 'http://www.myserver.com',
CURLOPT_USERAGENT => 'Chrome/22.0.1207.1'
);
$safariOptions = array(
CURLOPT_URL => 'http://www.myserver.com',
CURLOPT_USERAGENT => 'Safari/537.1'
);
$curl->setResponse('fallback response');
$curl->setResponse('default response from myserver.com'
$defaultOptions);
$curl->setResponse('response for Chrome from myserver.com',
$chromeOptions);
$curl->setResponse('response for Safari from myserver.com',
$safariOptions);
$cut = new ClassUnderTest($curl);
// Insert assertions to check whether $cut handles the
// different responses correctly
...
}
Вы можете сделать свой ответ зависимым от любой комбинации любых опций cURL. Конечно, вы можете пойти еще дальше. Например, ваш ClassUnderTest
берет некоторые XML-данные с сервера и анализирует их (ну, у вас должно быть два отдельных класса для этих задач, но давайте предположим, что это для нашего примера), и вы хотите протестировать это поведение. Вы можете загрузить XML-ответ вручную, и ваш тест прочитает данные из файла и вставит их в ответ. Затем вы точно знаете, какие данные есть, и можете проверить, правильно ли они проанализированы. В качестве альтернативы вы могли бы реализовать SAI_CurlInterface
загрузку всех ответов из вашей файловой системы сразу, но существующая реализация, безусловно, является точкой для начала.
В то время, когда я пишу этот ответ, @ SAI_CurlStub @ еще не поддерживает мультибиблиотечные функции cURL, но я планирую реализовать это и в будущем.
Надеюсь, эта заглушка поможет всем, кто хочет провести модульное тестирование классов, зависящих от cURL. Не стесняйтесь проверять и использовать классы, или внести свой вклад, конечно же - это на GitHub в конце концов :). Кроме того, я открыт для любой конструктивной критики в отношении реализации и использования интерфейса и заглушки.