2017-06-22 2 views
0

J'essaie de tester si une méthode d'une classe de base a été appelée et exécutée en utilisant un test Google Mock. J'ai une classe BankAccount simple qui implémente une fonction de retrait. Dans le fichier BankAccount.h:Comment tester si une méthode d'une classe de base a été appelée et exécutée en utilisant google mock?

class BankAccount { 

public: 

    BankAccount(); 

    int withdraw(int balance, int withdrawalAmount); 

}; 

Dans le fichier BankAccount.cpp:

#include "BankAccount.h" 

BankAccount::BankAccount() 
{ 
} 

int BankAccount::withdraw(int balance, int withdrawalAmount) 
{ 
    if (withdrawalAmount <= balance) 
    { 
     balance -= withdrawalAmount; 
    } 

    return balance; 
} 

Dans un fichier test.h je:

#include "BankAccount.h" 

class MockBankAccount : public BankAccount { 

public: 

    MockBankAccount(); 

    MOCK_METHOD2(withdraw, int(int balance, int withdrawalAmount)); 
}; 

Ma classe MockBankAccount hérite de BankAccount classe.

Dans mon fichier test.cpp:

#include <gtest/gtest.h> 
#include <gmock/gmock.h> 
#include "test.h" 

using namespace testing; 

// Constructors/Destructors 

MockBankAccount::MockBankAccount() 
{ 
} 

TEST(WithdrawAccountTest, Withdraw) 
{ 
    MockBankAccount mockAccount; 

    EXPECT_CALL(mockAccount, withdraw(5, 1)) 
     .Times(1); 

    mockAccount.withdraw(5, 1); 
} 

// Main 
int main(int argc, char* argv[]) 
{ 
    InitGoogleTest(&argc, argv); 
    InitGoogleMock(&argc, argv); 
    return RUN_ALL_TESTS(); 
} 

Je veux vérifier que la méthode est appelée retrait et exécutée à partir de la classe CompteBancaire (à savoir BankAccount :: retirer est exécuté). Quand j'exécute le test, il passe et je pense que le retrait a été appelé et exécuté, cependant si je place un point d'arrêt sur BankAccount :: remove et debug, je peux voir qu'il n'atteint jamais la méthode de la classe de base. Existe-t-il un moyen d'utiliser Google Mock pour vérifier BankAccount :: remove, par exemple en utilisant une autre méthode (composition plutôt qu'héritage, modèles, etc.)?

Répondre

0

Je veux essayer de vous donner une réponse acceptable.

Tout d'abord, le code fait ce qu'il est supposé être. Vous appelez dans le test la "méthode fictive" et le test passe bien sûr. Mais le test n'appellera jamais la méthode de la classe de base (et c'est correct). Au fait, cela n'a pas de sens de tester, si une méthode est appelée, puis d'appeler directement cette méthode.

Mais laisse parler de Mocking. Vous avez juste besoin de Mocks, lorsque la classe testée a des dépendances avec d'autres classes.
Considérons une classe Person, qui dépend de la classe BankAccount et que vous souhaitez tester la classe Person. Lors des tests, il est important de tester un objet isolément. C'est pourquoi vous ne voulez pas, que Person a parlé à une instance réelle de la classe BankAccount. Et voilà les moqueries ...

Imaginez qu'il ya la personne de classe en plus de vos classes:

class Person { 
public: 
    Person(BankAccount *account, int balance) : ba(account), balance(balance) {} 
    int getMoneyfromBankAccount(int withdrawalAmount) { 
     ba->withdraw(balance, withdrawalAmount); 
    } 
private: 
    BankAccount *ba; 
    int balance; 
} 

et les changements de test à:

TEST(PersonTest, testWhenPersonGetsMoneyFromTheBankAccount_withdrawIsCalled) 
{ 
    MockBankAccount mockAccount; 

    EXPECT_CALL(mockAccount, withdraw(5, 1)) 
     .Times(1); 

    Person p(&mockAccount, 5); 
    p.getMoneyfromBankAccount(1); 
} 

et ne pas oublier pour rendre la méthode de compte bancaire virtuelle:

virtual int BankAccount::withdraw(int balance, int withdrawalAmount) 

Après tout, si vous voulez juste tester la méthode withdraw() de la classe BankAccount, vous n'avez pas besoin de faux-semblants.