Я начинаю использовать CppUTest для некоторых проектов на C/C++. Особенно смешное расширение звука хорошее, но я в настоящее время борется, как правильно настроить насмешки. Предположите класс низкого уровня для абстрагирования сетевого сокета.CppUTest: как передать больше данных на определенный макет?
Мой первый метод:
size_t CMockSocket::recv(void* buf, size_t len) { return (size_t) mock().actualCall("recv") .withParameter("len", (int) len) .returnValue().getIntValue(); }
Настройка ожидания:
mock().expectOneCall("recv") .withParameter("len", 20) .andReturnValue(15);
До сих пор так хорошо. Но мне нужно будет предоставить больше данных - в этом случае 15 байт, которые я хочу вернуть с помощью указателя buf. Я попытался использовать методы .setData()
и setDataObject()
. Но похоже, что эти функции хранят данные в именованных переменных, а не с ожидаемым вызовом функции. Поэтому последующие вызовы будут отменять предыдущие данные, правильно?
Моя текущая проблема заключается в том, как я могу передать дополнительные , возвращая данные для издевательского метода? Мой первый аспект для этого заключался в создании результирующего класса, который содержит как возвращаемое значение (size_t), так и буфер данных. Как это:
class CRecvResults { public: size_t m_returnValue; void* m_buffer; CRecvResults(size_t returnValue, void* buffer) : m_returnValue(returnValue), m_buffer(buffer) {} ~CRecvResults() {} }; size_t CMockSocket::recv(void* buf, size_t len) { CRecvResults* pResults = (CRecvResults*) mock().actualCall("recv") .withParameter("len", (int) len) .returnValue().getPointerValue()); assert(pResults != NULL); assert(buf != NULL); assert(len >= pResults->m_buffer.length()); memcpy(buf, pResults->m_buffer.data(), pResults->m_buffer.length()); return pResults->m_returnValue; }
И ожидание:
char* buffer = "some returning buffer content at least 15 chars long"; CRecvResults results(15, buffer); mock().expectOneCall("recv") .withParameter("len", 20) .andReturnValue(&results);
Вопрос: это правильный путь или я что-то пропустила? Мне нужен буферный контент, потому что мне нужно протестировать интерпретатор результатов.
Мой второй метод:
bool CMockSocket::send(const void* buf, size_t len) { return mock().actualCall("send") .withParameter("len", (int) len) .returnValue().getIntValue(); }
Настройка ожидания:
mock().expectOneCall("send") .withParameter("len", 20) .andReturnValue(true);
В этом случае я хочу, чтобы проверить исходящие данные в BUF, сгенерированные кодом испытуемой. Поэтому мне нужно вернуть содержимое буфера (и длину) в тестовую функцию. Как это:
class CSendResults { public: bool m_returnValue; char* m_buffer; size_t m_length; CSendResults(bool returnValue, char* buffer, size_t length) : m_returnValue(returnValue), m_buffer(buffer), m_length(length) {} ~CSendResults() {} }; bool CMockSocket::send(const void* buf, size_t len) { CSendResults* pResults = (CSendResults*) mock().actualCall("send") .returnValue().getPointerValue(); assert(pResults != NULL); assert(buf != NULL); assert(pResults->m_length >= len); memcpy(pResults->m_buffer, buf, len); pResults->m_length = len; return pResults->m_returnValue; }
И ожидание:
char buffer[1024]; CSendResults results(true, buffer, sizeof(buffer); mock().expectOneCall("send") .withParameter("len", 20) .andReturnValue(&results); // further checks for results content...
Это выглядит очень некрасиво и с большим количеством накладных расходов для меня. Опять мой вопрос: это правильный путь или мне что-то не хватает?
И мой последний вопрос: может быть, я тестирую совершенно неправильный путь? Пожалуйста, дайте мне знать о вашем опыте и практике!
Thats хорошие новости! Я скоро проверю это, выгляжу как чистое решение. – Andi
BTW, в какой версии эта функция добавлена? – Andi
Он представлен в версии 3.6. С тех пор было много улучшений, поэтому стоит взглянуть на нынешнюю голову. –