Типичный способ написать тест с такой зависимостью, как это было бы найти решение для отправки времени выполнения. Существует как минимум два простых подхода. Одной из этих реализаций является «реальная» реализация. Это завершает recv . Другой - это «фальшивая» реализация. Вызовы виртуальной функции и динамическая диспетчерская в среде выполнения. Предоставьте решение здесь.
[*] Используйте std :: variant (или аналогично). В этом случае простой оператор IF может использоваться для переключения между реальными и макетными вызовами функций во время выполнения. Возможно, можно будет использовать contexpr или какое -то другое решение о компиляции, чтобы переключаться между вызовом двух реализаций функции. В этом случае зависимостью может быть тип t , введенный с использованием параметра шаблона.
Код: Выделить всё
ssize_t do_logic(
const int sock_fd,
const std::unique_ptr &p_buffer,
const size_t buffer_size
) {
// imagine there is some code block here
{
// code block A
}
ssize_t recv_size = recv(sock_fd, p_buffer.get(), buffer_size, 0);
// imaging there is some code block here
{
// code block B
}
return recv_size;
}
int main() {
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
// this is all just MWE noise
sockaddr_in server_address;
std::memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(1234);
bind(sock_fd, reinterpret_cast(&server_address), sizeof(server_address));
listen(sock_fd, 10);
const size_t buffer_size = 1024;
const auto p_buffer = std::make_unique(buffer_size);
do_logic(sock_fd, p_buffer, buffer_size);
return 0;
}
- Функция do_logic зависит от Recv . (Функция из библиотеки сокетов.) < /Li>
также имеет дополнительный код, который я пытаюсь избежать повторения. (Сухо) Они представлены кодовыми блоками Block A и Block B .
Код: Выделить всё
do_logic
Код: Выделить всё
int main() {
std::string sock_data = "Hello World. This is some example data for unit testing."
const size_t buffer_size = 1024;
const auto p_buffer = std::make_unique(buffer_size);
do_logic(sock_data, p_buffer, buffer_size);
return 0;
}
< /code>
Пока все хорошо. Мы можем написать реализацию do_logic Код: Выделить всё
ssize_t do_logic(
std::string sock_data,
const std::unique_ptr &p_buffer,
const size_t buffer_size
) {
// imagine there is some code block here
{
// code block A
}
ssize_t recv_size = recv(sock_data, p_buffer.get(), buffer_size);
// imaging there is some code block here
{
// code block B
}
return recv_size;
}
< /code>
Проблема здесь является нарушением сухой. Хотя это будет работать, не идеально поддерживать синхронизацию двух кодовых блоков в двух разных файлах в кодовой базе. Эти файлы, вероятно, находятся в очень разных местах в дереве источника, поскольку один из этих файлов предназначен для модульного тестирования, в то время как другой предназначен для производственного кода. (Не показано здесь, но это, вероятно, назвал бы std :: copy Есть ли решение этой проблемы, которая не требует прибегания к отправке времени выполнения? Это своего рода инъекция зависимости, когда тип вводится в функцию.
Код: Выделить всё
template
ssize_t do_logic(
T sock,
const std::unique_ptr &p_buffer,
const size_t buffer_size
) {
// imagine there is some code block here
{
// code block A
}
constexpr if ( /* ? */ ) {
// this `recv`: the `recv` from the sockets library
ssize_t recv_size = recv(sock, p_buffer.get(), buffer_size, 0);
}
else {
// this `recv`: an implementation of a function `recv(std::string, ...etc...)`
// which we write. It could be a null implementation, or it could call
// `std::copy`.
//
// ssize_t recv(std::string, const auto& p_buffer, const auto buffer_size) { return 0; }
//
ssize_t recv_size = recv(sock, p_buffer.get(), buffer_size);
}
// imaging there is some code block here
{
// code block B
}
return recv_size;
}
constexpr if ( T isa typename int ) { }
else if ( T isa typename std::string ) { }
else {
static_assert("T must be either type int or type std::string");
}
< /code>
Однако я понятия не имею, как это реализовать. Я смутно осознаю, что C ++ 20 (?) Представил концепции. Однако из моего первоначального чтения в понятиях моя интерпретация заключалась в том, что концепции - это более абстрактная идея, которую группы связывают типы вместе. Я не уверен, является ли это правильным инструментом для работы? Вполне вероятно, что я принимаю это в неправильном направлении. Отзывы об этом будут очень оценены. Заранее спасибо.
Подробнее здесь: https://stackoverflow.com/questions/794 ... mplates-in
Мобильная версия