开发者

Confused about testing an interface implementing method in C++.. how can I test this?

Please, consider the following (I'm sorry for the amount of code; but this is the minimal example I could think of...):

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

I would like to test SomeFilter::calculate, here. The problem is that the constructor for SomeDataBlock calls out to the filesystem. SomeDataBlock itself is tested by a mock IFileSystemProvider. However, I don't have a simple way to inject the mock into SomeFilter::Calculate; and unfortunately I cannot change the IFilter interface to allow the mock to be passed as an argument to Calculate, because there are other filters for which such a mock would not make any sense.

How can I test Calculate?


Can you modify the constructor of SomeFilter? If so, you can inject IFileSystemProvider that way.

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

You could also create a public member on SomeFilter to allow the user to provide IFileSystemProvider, before calling Calculate, but after constructing the object.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜