Как написать модульный тест для сетевого клиента?

Мне нужно написать простой http-клиент. Было бы здорово иметь модульные тесты для моего класса. Но я не знаю, как написать правильный и тестируемый класс.

Например, у меня есть такой клиент:

class HTTPClient
{
public:
     HTTPCLient(const std::string& host, const std::string& port): session(host, port) {}

     void send()
     {
         session.sendRequest(someRequest);
         Response response = session.receiveResponse();
         // ...
     }

private:
    SomeLibrary::ClientSession session;
};

Как проверить метод send (что я действительно отправляю то, что хочу)? Я не могу издеваться над этим. Я могу написать, что HTTPClient получает SomeLibrary::ClientSession объект в конструкторе (в тесте я бы прошел mock), но хороший ли это дизайн? Я думаю, что способ реализации сеанса и т. д. должен быть скрыт в моем классе.

У тебя есть идеи?


person peter55555    schedule 07.04.2016    source источник


Ответы (3)


На днях я написал клиентскую библиотеку HTTP.

Чтобы протестировать клиентскую библиотеку HTTP, я просто написал простой тестовый код, который запускал std::thread прослушивание некоторого случайного порта на localhost. Затем я сказал клиенту сделать тестовый запрос с параметрами host и port, как в вашем случае, указывая на порт, который сейчас прослушивает мой поток. Код потока был запрограммирован так, чтобы принимать соединение, читать HTTP-запрос, сохранять его и затем отвечать готовым HTTP-ответом.

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

И, по большому счету, все это охранялось вызовом alarm(), поэтому, если что-то застряло в бесконечном цикле или около того, весь процесс в конечном итоге покончит с собой.

Таким же образом вы можете тестировать и свой собственный код.

person Sam Varshavchik    schedule 07.04.2016

Вставьте экземпляр абстрактного клиентского сеанса в конструктор. Смоделируйте его в модульных тестах и ​​передайте реальный экземпляр при работе по-настоящему.

Вы говорите, что не можете издеваться над этим в одном предложении, а в следующем говорите, что можете. Что вы имеете в виду? Если вы имеете в виду, что класс сеанса не является «вашим» или что он не может быть получен таким образом, чтобы его можно было издеваться таким образом, то пытались ли вы обернуть его в свой класс, чтобы он мог издеваться?

Кроме того, вы говорите: «Я думаю, что способ реализации сеанса и т. д. должен быть скрыт в моем классе».

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

person Johann Gerell    schedule 07.04.2016

вы можете имитировать простой HTTP-сервер с сокетом. может помочь следующий псевдокод:

1) set up a string to send from the client, take its length in before hand
2) open a new thread with a socket in it
3) bind the socket into some port , listen and accept new connection
4) send the string you have setted with your http client
5) in the socket side, read until the length you saved has reached, save that string for comparison
6) send some pre-defined http response
7) close the socket 
7) close the thread
8) continue testing, you have the string which the server got, and the string which the client got, and the original strings which these was originated from

имитировать передачу и перенаправления по частям легко, но имитировать SSL может быть довольно сложно. вы можете обернуть свой сокет некоторым потоком SSL, предоставленным потоком openSSL или Boost SSL.

другой вариант — использовать уже написанный HTTP-сервер на локальном хосте. написать один (только для тестирования) на Python или Node.js довольно просто и подходит для этой задачи тестирования. перед запуском теста активируйте серверный скрипт (со скриптом Node.js это просто как system("node myServer.js")), а когда тест завершится, уничтожьте этот сервер.

person David Haim    schedule 07.04.2016