考虑以下代码:
class SomeInterface
{
public:
virtual void foo() = 0;
virtual ~SomeInterface() {}
};
class RealImplementation : public SomeInterface
{
public:
void foo() { /* do complete stuff */}
};
class MockImplementation : public SomeInterface
{
public:
void foo() { /* do simple stuff */ }
};
更具体的有一些例子:
class IInjector
{
public:
virtual bool injectDLL() const = 0;
virtual ~IInjector() {}
};
class RealInjector : public IInjector
{
public:
bool injectDLL() const
{
int pid = GetHookedProcessId();
char name = readDllNameFromSomewhere();
if (loadDllInSomeProcess(pid, name))
return true;
else
return false;
}
};
class Hook
{
public:
bool hookProcess(const IInjector& injector)
{
return injector.injectDLL();
}
};
然后在测试代码中,常见的情况是做这样的事情:
class MockInjector : public IInjector {
public:
MOCK_METHOD0(injectDLL, bool());
};
TEST(HookTest, CanHookSomething) {
MockInjector injector;
EXPECT_CALL(injector, injectDLL()).Times(1);
Hook hook;
EXPECT_TRUE(hook.hookProcess(injector));
}
为了验证 injectDLL
方法被调用,我们必须知道 hookProcess
调用了 injectDLL
。而是方法hookProcess
的实现细节。因此,在我们的测试中,我们公开了一些实现细节。但这是很常见的情况。那么,在使用mocks的时候公开一些实现细节是否可以呢?
最佳答案
单元测试通常用作白盒测试技术——您知道被测试的代码。否则,您也无法对测试实现的代码覆盖率做出声明。并且,单元测试代码被视为属于代码,与代码等一起置于版本控制之下。因此,对于您的单元测试,您不会“公开”实现细节 - 它们无论如何都不会隐藏。
但是,通过模拟,您的测试肯定会变得更加依赖于实现细节,这意味着它们更有可能中断或需要维护。但这只是您在这种情况下可能必须接受的权衡。
关于c++ - 期望在模拟对象上调用某些方法。它会破坏封装吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55481902/