GoogleTest 模拟 C++ 单例

GoogleTest Mock C++ singleton

我正在尝试找出 best/preferred 模拟单例对象的方法。

我这里有一个 class 单身人士。

class Singleton {

public:

static std::shared_ptr<Singleton> getInstance() {
    static std::shared_ptr<Singleton> instance =
            std::make_shared<Singleton>(); // Guaranteed to be destroyed.
    // Instantiated on first use.
    return instance;
}

Singleton(Singleton const&) = delete;
Singleton(Singleton &&) = delete;
Singleton& operator=(Singleton const&) = delete;
Singleton& operator=(Singleton &&) = delete;
~Singleton();

void flush();

}

使用 Foo class 在某个时候调用单例...

#include <Foo.h>
#include <Singleton.h>

void Foo::action(int value) {

    if (value > 1) {
        Singleton::getInstance()->flush();
    } else {
        // do nothing
    }
}

我想模拟 Singleton 对象有跟随 FooTest 以确保调用 flush 方法。

TEST_F(FooTest, testFlushIsCalled) {
    auto foo = Foo();
    foo.someAction(2);
    EXPECT_CALL(Singleton::getInstance(), flush()).Times(1);
}

提前致谢!!

单例非常模拟起来很麻烦(并且通常在单元测试中很痛苦)。

如果你能用依赖注入替换单例调用,你会减轻很多痛苦,并且可以使用标准方法来模拟它,即

Foo::Foo(Singleton* flushSingleton) : myFlushSingletion(flushSingleton) {};

void Foo::action(int value) {
    if (value > 1) {
        myFlushSingletion->flush();
    } else {
        // do nothing
    }
}

如果您无法使用更黑暗的魔法 - 但后果自负...
您可以将(本地静态)Singleton 实例变成受保护的静态变量(及其函数虚拟)

class Singleton {
//...
protected:
static std::shared_ptr<Singleton> mySingletonInstance;
//...
}

然后你可以派生一个 MockSingleton,它将自己置于真正的 Singleton 的 mySingletonInstance 中 - 但正如我所说的......更好地重构你的代码,你将来会更快乐。