Nous utilisons un modèle objet simple pour notre code réseau de bas niveau au travail où les pointeurs de structure sont passés à des fonctions qui prétendent être des méthodes. J'ai hérité la plupart de ce code qui a été écrit par des consultants avec une expérience C/C++ passable au mieux et j'ai passé beaucoup de nuits en essayant de refactoriser le code en quelque chose qui ressemblerait à une structure raisonnable.Comment est-ce que je moque des objets sans héritage (en C)?
Maintenant, je voudrais apporter le code sous test unitaire mais vu le modèle d'objet que nous avons choisi je n'ai aucune idée de comment se moquer des objets. Voir l'exemple ci-dessous:
tête de l'échantillon (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_ */
source d'échantillon (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;
}
Dans l'exemple ci-dessus, je voudrais se moquer de la TcpSocket objet afin que je puisse apporter "foo_transmit_command" sous test unitaire mais je ne suis pas sûr de savoir comment procéder à ce sujet sans héritage. Je ne veux pas vraiment reconcevoir le code pour utiliser vtables sauf si je dois vraiment le faire. Peut-être qu'il y a une meilleure approche à cela que de se moquer? Mon expérience de test vient principalement de C++ et j'ai un peu peur que je me sois peinte dans un coin ici. J'apprécierais hautement les recommandations de testeurs plus expérimentés.
Edit:
Comme Richard Quirk a souligné qu'il est vraiment l'appel à « tcp_socket_send » que je veux passer outre et je préférerais le faire sans enlever le vrai symbole de tcp_socket_send de la bibliothèque lors de la liaison le test depuis il est appelé par d'autres tests dans le même binaire.
Je commence à penser qu'il n'y a pas de solution évidente à ce problème ..
Je pourrais probablement le mettre dans l'entête TcpSocket et le placer dans #ifdef TESTING .. #endif. Bonne suggestion. –
Vous connaissez mieux votre code je voulais juste dire que la macro est une chose totale et la macro placée au mauvais endroit peut conduire au problème qui est vraiment difficile à déboguer – Ilya