2017-09-26 4 views
2

Je me moque d'une bibliothèque C (..ughh) contenant des fonctions qui prennent comme argument "des structures avec des pointeurs". Mon but est de faire des attentes sur les données que ces pointeurs pointent vers. Les fonctions de la bibliothèque consomment immédiatement leurs arguments. c'est-à-dire que ces structures peuvent sortir du cadre après que la fonction est appelée.Meilleure approche des fonctions de moquerie qui ont besoin de consommer des arguments directement

dans le code:

struct A 
{ 
    B* somePointer; 
} 

class ClassUnderTest 
{ 
public: 
    ClassUnderTest() 
    { 
     B arbitraryStruct; 
     A structArg; 
     structArg.somePointer = &arbitraryStruct; 
     C_LibraryFunction(&A); 
    } 
}; 

ma solution est de sauver l'argument en définissant une gtest 'action'. dans cette action sauve arbritraryStruct à un peu de monde et fais ma magie d'attente. par exemple.

B arbitraryStruct; 
ACTION(captureB) 
{ 
    const A* a= arg0; 
    arbitraryStruct = *a->somePointer; 
} 

Test(TestClassUnderTest, testIt) 
{ 
    EXPECT_CALL(clibrary, 
    C_libraryFunction(testing::_)).WillOnce(DoAll(captureB()); 
    ClassUnderTest classUnderTest; 

    EXPECT_EQ(bla, B.arbitraryStruct); 
} 

cela fonctionne, mais il se sent un peu complet. Il y a beaucoup d'appels de cette bibliothèque dont j'ai besoin de me moquer et certains contiennent des structures complexes. En tant que programmeur paresseux, on a l'impression que cela peut être fait d'une meilleure façon. quelqu'un peut-il proposer une meilleure approche?

Merci!

Répondre

1

Une meilleure façon est pas de le faire. Au lieu de cela, vous devez créer une classe en utilisant ces fonctions et mocker cette classe à la place. Cette classe doit être aussi simple que possible, afin d'éviter d'éventuels bugs.

Par exemple:

struct MyIface { 
    virtual ~MyIface(){} 

    virtual void Clog() = 0; 
}; 

struct VeebleFitzer { 
    VeebleFitzer() : a(funcA()) { 
    } 
    virtual void Clog() { 
    funcX(a); 
    funcY(); 
    } 

    int a; 
}; 

Ensuite, utilisez une sorte d'injection de dépendance à passer des objets là où ils sont nécessaires.


Vous pouvez toujours créer des tests fonctionnels, où vous utilisez des ressources réelles (y compris « réel », et non Mock, fonctions), pour tester votre code.

+0

merci pour les commentaires! vous avez tout à fait raison, c'est plus propre à définir une interface pour abstraire un composant externe, (dans mon cas une API vulkan). Maintenant, j'y pense, ce que j'essaie de faire, c'est de mettre à l'épreuve cette «couche de conversion». peut-être pas une bonne idée de continuer ce chemin ... le défi ici est que la performance sur certaines parties est vraiment clé et je ne suis pas sûr que je peux rester simple dans ce domaine, mais c'est une autre discussion –

+0

@SvenRademakers Cela dépend de ce que vous voulez faire. Les tests fonctionnels devraient faire ce que vous voulez - écrivez des tests avec gtest en utilisant des fonctions réelles (ne les moquez pas). Si vous souhaitez tester la fonctionnalité ci-dessus, effectuez les tests unitaires et simulez les fonctionnalités ci-dessous. –