سؤال

I'm pretty deep into unit tests right now and have encountered a rather advanced problem.
There's this class TrackLoader, which has a method called loadTracks(...). I'd like to test that method - without depending on a file system - and this is where it gets tricky

It's a rather complex problem (imho), so maybe some code would be helpful

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

The main problem is, that the actual Importer tries to load the file from the given path. To break file-system-dependency I'd have to mock Importer::parseTrack() and Importer::getTrack to return valid Tracks (without touching the file system).
But I don't see a way to mock the actual Importer. I could mock the ImporterFactory (making ::createImporter non-static), but how would I mock the Importer itself?

Can this be done without refactoring the code itself?

هل كانت مفيدة؟

المحلول

After some fiddling I actually managed to solve the problem.
Here's the code:

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

Basically, ImporterFactory was first mocked to ensure that it creates any Importer at all.
By adding the .WillOnce(Return(datImporter)) bit, I was able to inject a MockImporter through the MockImporterFactory.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top