Запутался в тестировании метода реализации интерфейса в C ++. Как я могу это проверить? - PullRequest
1 голос
/ 27 августа 2010

Пожалуйста, примите во внимание следующее (извините за объем кода; но это минимальный пример, который я могу придумать ...):

class SomeDataThingy
{
};

struct IFileSystemProvider
{
    virtual ~IFileSystemProvider() {}
    //OS pure virtual methods
}

struct DirectFileSystemProvider
{
    //Simply redirects the pure virtuals from IFileSystemProvider to OS functions.
}

struct SomeDataBlock
{
    //Stored inside SomeDataThingy; contains specific data
    SomeDataBlock(const SomeDataThingy& subject, const IFileSystemProvider& os = DirectFileSystemProvider())
    {
        //Calculate some data from the Operating System based upon a filename stored in SomeDataThingy.
    }
};

struct IFilter
{
    virtual ~IFilter() {}
    virtual int Matches(const SomeDataThingy&) const = 0;
    virtual void Calculate(SomeDataThingy&) const = 0;
};

class SomeFilter : public IFilter
{
    int Matches(const SomeDataThingy& subject) const
    {
        if (!Subject.Contains<SomeDataBlock>())
            return UNKNOWN;
        else
            return /* This filter matches */
    }
    void Calculate(SomeDataThingy& subject) const
    {
        std::auto_ptr<SomeDataBlock> data(new SomeDataBlock(subject));
        subject.Install<SomeDataBlock>(data);
    }
};

Я бы хотел проверить SomeFilter::calculate здесь. Проблема в том, что конструктор SomeDataBlock обращается к файловой системе. SomeDataBlock сам по себе тестируется макетом IFileSystemProvider. Однако у меня нет простого способа ввести макет в SomeFilter::Calculate; и, к сожалению, я не могу изменить интерфейс IFilter, чтобы позволить макету передаваться в качестве аргумента Calculate, потому что есть другие фильтры, для которых такой макет не имеет никакого смысла.

Как я могу проверить Calculate?

1 Ответ

5 голосов
/ 27 августа 2010

Можете ли вы изменить конструктор SomeFilter? Если это так, вы можете внедрить IFileSystemProvider таким образом.

class SomeFilter : public IFilter
{
public:
    SomeFilter(const IFileSystemProvider& fs = DirectFileSystemProvider())
        : fs(fs)
    {
    }

private:
    int Matches(const SomeDataThingy& subject) const
    {
        if (!Subject.Contains<SomeDataBlock>())
            return UNKNOWN;
        else
            return /* This filter matches */
    }
    void Calculate(SomeDataThingy& subject) const
    {
        std::auto_ptr<SomeDataBlock> data(new SomeDataBlock(subject, fs));
        subject.Install<SomeDataBlock>(data);
    }

    IFileSystemProvider fs;
};

Вы также можете создать открытый элемент в SomeFilter, чтобы позволить пользователю предоставлять IFileSystemProvider перед вызовом Calculate, но после создания объекта.

...