c++ - 期望在模拟对象上调用某些方法。它会破坏封装吗?

标签 c++ unit-testing mocking googletest googlemock

考虑以下代码:

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/

相关文章:

unit-testing - 如何在抛出错误时忽略 Jest 中的空测试文件

objective-c - 如何使 XCode 4 的逻辑单元测试从 Nib 正确初始化 UIViewController?

android - 如何防止 ActivityUnitTestCase 调用 Application.onCreate?

mocking - PHPUnit 模拟多重期望

c++ - 你能防止 istream 或 stringstream 吞掉换行符吗?

c++ - 测试无效的窗口句柄 : should I compare with 'NULL' , '0' 甚至 'nullptr' ?

c++ - 从命令行编译 wxWidgets

c++ - 在 C++ 中使用表示变量名称的字符串访问变量值

c# - 为什么我们需要模拟框架?

ruby-on-rails - 如何在 rspec 中模拟数据库查询响应以根据响应测试其他方法