使用TDD时隐藏文件访问实施细节

时间:2017-06-02 06:26:36

标签: c++ interface tdd

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

问题在于:为了能够模拟文件访问,我必须引入一个Wi​​nApiInterface(或任何你想要调用它的文件,如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_;
}

1 个答案:

答案 0 :(得分:0)

如果您的主要目标是让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方法。