2015-10-26 1 views
1

J'ai le code qui interagit avec le système de fichiers en utilisant boost qui ressemble à:Comment simuler le lancement d'une exception?

FileMigrater::migrate() const { 
    //stuff 
    try { 
     boost::filesystem::create_direcotry(some_path_); 
    } catch(const std::exception& e) { 
     LOG(ERROR) << "Bad stuff happened"; 
     return MigrationResult::Failed; 
    } 
    //more stuff 
} 

J'utilise gmock et gtest pour écrire des tests unitaires pour la méthode migrate et je voudrais écrire un test pour le cas où boost lève une exception. Idéalement, je voudrais écrire un test unitaire qui ressemble à (la syntaxe de ce sera mal parce que je suis nouveau C++ en général):

TEST_F(MyTest, boost_exception_test) { 
    ON_CALL(boost_mock, create_directory()).Throw(std::exception); 

    EXPECT_EQ(Migration::Failed, migrater.migrate()); 
} 

Le problème est que je ne sais pas comment pour créer le boost_mock ou même si c'est la bonne approche du problème.

+0

Mon approche: il s'asseoir Silencieusement et votre avatar facepalm chaque fois boost lance une telle exception – sehe

Répondre

1

Votre approche de test est assez bonne. Le point est que ne peut pas se moquer des fonctions libres et boost::filesystem::create_directory() en est une.

Cependant, la documentation suggère une approche de travail autour d'elle:

Il est possible d'utiliser Google Mock pour se moquer d'une fonction libre (à savoir une fonction C-style ou une méthode statique). Vous avez juste besoin de réécrire votre code pour utiliser une interface (classe abstraite).

Au lieu d'appeler une fonction libre (disons, OpenFile) directement, introduire une interface pour elle et une sous-classe concrète qui appelle la fonction libre:

class FileInterface { 
public: 
... 
virtual bool Open(const char* path, const char* mode) = 0; 
}; 
class File : public FileInterface { 
public: 
... 
virtual bool Open(const char* path, const char* mode) { 
    return OpenFile(path, mode); 
} 
}; 

Votre code devrait parler FileInterface pour ouvrir un fichier. Maintenant, il est facile de se moquer de la fonction. Cela peut sembler fastidieux, mais en pratique, vous avez souvent plusieurs fonctions liées à que vous pouvez placer dans la même interface, de sorte que la surcharge syntaxique par fonction sera beaucoup plus faible.

Si vous êtes préoccupé par les frais généraux de performance encourus par fonctions virtuelles, et le profilage confirme votre préoccupation, vous pouvez combiner cela avec la recette de mocking non-virtual methods.

+0

ma classe 'FileMigrater' devrait alors prendre un' FileInterface' comme une dépendance dans le constructeur, non? –

+1

Oui, vous devez injecter la dépendance quelque part. L'utilisation du constructeur est une commune. Vous pouvez également avoir un membre statique dans 'FileMigrater' si vous ne voulez pas conserver de référence pour chaque instance et vous pouvez partager le même objet' FileInterface'. –

+0

génial, merci! :) –