Как бы я высмеял объект, созданный в "тестируемом методе"?

Я сейчас довольно глубоко разбираюсь с юнит-тестами и столкнулся с довольно сложной проблемой.
Есть этот класс TrackLoader, у которого есть метод loadTracks (...). Я хотел бы протестировать этот метод - без зависимости от файловой системы - и вот где он становится сложным

Это довольно сложная проблема (imho), поэтому, возможно, какой-то код будет полезен

void TrackLoader::loadTracks(QDomNode tracks, DataManager& dataManager)
{       
    QDomNodeList trackList = tracks.childNodes();

    for(int i = 0; i < trackList.size(); ++i)
    {
      QString filePath = trackList.at(i).toElement().attribute("filePath");

      QSharedPointer<Importer> importer = ImporterFactory::createImporter(filePath);
      importer->parseTrack();
      dataManager.addTrack(filePath, importer->getTrack());          
}

Основная проблема заключается в том, что фактический импортер пытается загрузить файл по указанному пути. Чтобы сломать зависимость файловой системы, мне нужно было бы смоделировать Importer::parseTrack() и Importer::getTrack, чтобы вернуть действительные треки (не касаясь файловой системы).
Но я не вижу способа издеваться над настоящим импортером. Я мог бы издеваться над ImporterFactory (делая::createImporter нестатичным), но как бы я высмеял сам Importer?

Можно ли это сделать без рефакторинга самого кода?

1 ответ

Решение

После некоторой возни мне действительно удалось решить проблему.
Вот код:

//this Importer is used to create mockTracks
std::shared_ptr<MockImporter> datImporter = std::make_shared<MockImporter>();
EXPECT_CALL(*(datImporter.get()), parseSource()).Times(3);
EXPECT_CALL(*(datImporter.get()), getSource()).Times(3).WillRepeatedly(Return(mockedTrack()));

//this factory is used to inject the actual MockImporter
std::shared_ptr<MockImporterFactory> importerFactory = std::make_shared<MockImporterFactory>();
EXPECT_CALL(*(importerFactory.get()), createImporter(QString("Test1.DAT"))).WillOnce(Return(datImporter));
EXPECT_CALL(*(importerFactory.get()), createImporter(QString("Test2.DAT"))).WillOnce(Return(datImporter));
EXPECT_CALL(*(importerFactory.get()), createImporter(QString("Test3.DAT"))).WillOnce(Return(datImporter));

//this injects the MockImporterFactory and runs the code.
TrackLoaderPtr trackLoader = std::make_shared<TrackLoader>(importerFactory);
trackLoader->loadTracks(identNode(), _dataManager);

По сути, ImporterFactory был сначала осмеян, чтобы убедиться, что он вообще создает любого Importer.
Добавив бит.WillOnce(Return(datImporter)), я смог внедрить MockImporter через MockImporterFactory.

Другие вопросы по тегам