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.
精彩评论