我如何模拟在'测试中的方法'中创建的对象?

时间:2013-05-30 09:40:26

标签: unit-testing googletest gmock

我现在非常深入到单元测试中并且遇到了相当高级的问题。
这个类的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尝试从给定路径加载文件。要打破文件系统依赖性,我必须模拟Importer :: parseTrack()和Importer :: getTrack来返回有效的Tracks(不触及文件系统)。
但我没有看到嘲笑实际进口商的方法。我可以模拟ImporterFactory(使:: createImporter非静态),但是如何模拟Importer本身呢?

这可以在不重构代码的情况下完成吗?

1 个答案:

答案 0 :(得分:2)

经过一番摆弄,我实际上设法解决了这个问题。
这是代码:

//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))位,我能够通过MockImporterFactory注入MockImporter。