Мы используем простую объектную модель для нашего низкоуровневого сетевого кода в работе, где указатели на структуру передаются функциям, которые притворяются методами. Я унаследовал большую часть этого кода, который в лучшем случае был написан консультантами с опытом прохождения C / C ++, и я провел много поздних ночей, пытаясь преобразовать код в нечто, напоминающее разумную структуру.
Теперь я хотел бы привести код к модульному тестированию, но, учитывая выбранную нами объектную модель, я понятия не имею, как имитировать объекты. Смотрите пример ниже:
Пример заголовка (foo.h):
#ifndef FOO_H_
#define FOO_H_
typedef struct Foo_s* Foo;
Foo foo_create(TcpSocket tcp_socket);
void foo_destroy(Foo foo);
int foo_transmit_command(Foo foo, enum Command command);
#endif /* FOO_H_ */
Источник выборки (foo.c):
struct Foo_s {
TcpSocket tcp_socket;
};
Foo foo_create(TcpSocket tcp_socket)
{
Foo foo = NULL;
assert(tcp_socket != NULL);
foo = malloc(sizeof(struct Foo_s));
if (foo == NULL) {
goto fail;
}
memset(foo, 0UL, sizeof(struct Foo_s));
foo->tcp_socket = tcp_socket;
return foo;
fail:
foo_destroy(foo);
return NULL;
}
void foo_destroy(Foo foo)
{
if (foo != NULL) {
tcp_socket_destroy(foo->tcp_socket);
memset(foo, 0UL, sizeof(struct Foo_s));
free(foo);
}
}
int foo_transmit_command(Foo foo, enum Command command)
{
size_t len = 0;
struct FooCommandPacket foo_command_packet = {0};
assert(foo != NULL);
assert((Command_MIN <= command) && (command <= Command_MAX));
/* Serialize command into foo_command_packet struct */
...
len = tcp_socket_send(foo->tcp_socket, &foo_command_packet, sizeof(foo_command_packet));
if (len < sizeof(foo_command_packet)) {
return -1;
}
return 0;
}
В приведенном выше примере я хотел бы смоделировать объект TcpSocket , чтобы я мог перенести "foo_transmit_command" в модульное тестирование, но я не уверен, как это сделать без наследование. Я действительно не хочу переделывать код, чтобы использовать vtables, если мне не нужно. Может быть, есть лучший подход к этому, чем издеваться?
Мой опыт тестирования в основном приходит из C ++, и я немного боюсь, что мог бы заглянуть сюда в угол. Буду очень признателен за рекомендации более опытных тестировщиков.
Edit:
Как отметил Ричард Квирк, это действительно вызов "tcp_socket_send" , который я хочу переопределить, и я бы предпочел сделать это без удаления реального символа tcp_socket_send из библиотеки при связывании теста, поскольку он вызывается другие тесты в том же двоичном файле.
Я начинаю думать, что нет очевидного решения этой проблемы ..