【问题标题】:Hide file access implementation details while using TDD使用 TDD 时隐藏文件访问实现细节
【发布时间】:2017-06-02 06:26:36
【问题描述】:

我正在尝试创建一个继承自 TableFileInterface 的 CsvTableFile 类。为了对类进行单元测试,我想模拟所有文件访问。

问题是:为了能够模拟文件访问,我必须引入一个 WinApiInterface(或任何你想调用的名称,如 FileIoInterface),它必须提供给 CsvTableFile 类的构造函数。然而,这向所有人展示了提交给 OpenFile 的实现。如果我想将内部从 OpenFile 更改为 ifstream,我必须更改构造函数,因为这样我不需要 WinApiInterface 来传递给类,而是 FileStreamInterface。

我对这种情况不是特别满意,但我想不出解决办法。我错过了什么吗?

class WinApiInterface {
public:
    virtual HFILE WINAPI OpenFile(
       _In_  LPCSTR     lpFileName,
       _Out_ LPOFSTRUCT lpReOpenBuff,
       _In_  UINT       uStyle ) = 0;
}

class WinApi : public WinApiInterface {
public:
    virtual HFILE WINAPI OpenFile(
       _In_  LPCSTR     lpFileName,
       _Out_ LPOFSTRUCT lpReOpenBuff,
       _In_  UINT       uStyle ) { 
           return ::OpenFile(lpFileName, lpReOpenBuff, lpReOpenBuff);};
}


class TableFileInterface {
public:
    virtual int Open(std::string file) = 0;
    virtual int Close() = 0;

    virtual std::string GetCellAsString(size_t row; size_t column) = 0;
    virtual double GetCellAsDouble(size_t row; size_t column) = 0;
}

class CsvTableFile : public TableFileInterface {
public:
    CsvTableFile(const WinApiInterface& win_api)
       : win_api_(win_api){};
    ~CsvTableFile(){};

    virtual int Open(std::string file) { *CODE USING win_api_.OpenFile(...)*};
    virtual int Close() {...};

    std::string GetCellAsString(size_t row; size_t column) {...};
    double GetCellAsDouble(size_t row; size_t column) {...};

protected:
    WinApiInterface win_api_;
}

【问题讨论】:

  • WinApiInterface 是一个抽象类,不能作为类成员实例化。您可以将其存储为普通引用或使用智能指针。
  • 定义一个只提供要处理的行的类的接口。然后,您的 CvsTableFile 类将采用一个实现此接口的对象来处理要处理的行。然后您可以编写一个实际从文件中读取的类,另一个用于测试的类等。
  • @smkanadl:你完全正确。
  • @Rene:非常聪明。我想我也要试试!谢谢你的回答!

标签: c++ interface tdd


【解决方案1】:

如果您在这里的主要目标是使CsvTableFile 无需更改,则可以对其进行模板化并将打开逻辑转移到模板参数对象。

template <class T>
class CsvTableFile : public TableFileInterface {
public:
    CsvTableFile(const T& _fileopener):fileopener(_fileopener){}

    int Open(std::string file) { fileopener.OpenFile(...); }

    T& fileopener;
    ...
};

然后为您要使用的每种文件处理类型创建一个类,并在每个类中实现OpenFile 方法。

【讨论】:

  • 好方法!这以一种优雅的方式解决了我的问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-09
  • 1970-01-01
  • 2012-03-19
  • 2017-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多