2015-10-26 2 views
1

У меня есть код, который взаимодействует с файловой системой, используя boost, которая выглядит как:Как высмеивать бросок за исключением?

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 
} 

Я использую gmock и gtest писать модульные тесты для метода migrate, и я хотел бы написать тест для случая где boost выдает исключение. В идеале, я хотел бы написать модульный тест, который выглядит примерно так (синтаксис это будет неправильно, потому что я новый C++ в целом):

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

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

Проблема заключается в том, что я не знаю, как для создания boost_mock или даже если это правильный подход к проблеме.

+0

Мой подход: Молча сидеть там и ваш аватар FACEPALM всякий раз, когда импульс бросает один такой исключение – sehe

ответ

1

Ваш подход к тестированию довольно хорош. Дело в том, что не может высмеять свободные функции и boost::filesystem::create_directory() - это один.

Однако documentation предполагает подход к работе вокруг него:

Можно использовать Google Mock издеваться свободную функцию (т.е. функцию C-стиля или статический метод). Вам просто нужно переписать код , чтобы использовать интерфейс (абстрактный класс).

Вместо вызова свободной функции (скажем, OpenFile) непосредственно, ввести интерфейс для него и есть конкретный подкласс, который вызывает свободную функции:

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); 
} 
}; 

Ваш код должны поговорить с FileInterface, чтобы открыть файл. Теперь легко издеваться над функцией.

Это может показаться много хлопот, но на практике у вас часто есть несколько связанных функций, которые вы можете поместить в один и тот же интерфейс, поэтому на синтаксические служебные данные для каждой функции будут значительно ниже.

Если вы обеспокоены накладных расходов, понесенных виртуальных функций и профилирование подтверждает ваше беспокойство, вы можете совместить это с рецептом mocking non-virtual methods.

+0

мой класс 'FileMigrater' должен затем взять в' FileInterface' как зависимость в конструкторе, не так ли? –

+1

Да, вы должны каким-то образом ввести зависимость. Использование конструктора является общим. У вас также может быть статический член в «FileMigrater», если вы не хотите хранить ссылку для каждого экземпляра, и вы можете использовать один и тот же объект «FileInterface». –

+0

awesome, спасибо! :) –