在C ++中对Singleton模式进行单元测试有哪些方法? (请举例说明)
答案 0 :(得分:11)
将单例的实现作为一个单独的类,并创建一个在外部实现“单例”的包装器。这样你就可以根据需要测试实现(除了单例行为,这是微不足道和不必要的。
class SingletonImpl {
public:
int doit(double,double);
};
class Singleton {
public:
Singleton& instance() {...}
int doit(double a,double b) {impl->doit(a,b);}
...
private:
SingletonImpl impl;
}
答案 1 :(得分:2)
假设我们有经典的单例反模式,它负责三件事:
class Singleton {
public:
// Globally accessible instance
static Singleton & instance();
// Public interface
void do_something();
private:
// Lifetime management
Singleton();
~Singleton();
}
和依赖于此的类:
class Dependent {
public:
Dependent() : s(Singleton::instance()) {}
void do_something_else();
private:
Singleton & s;
};
现在我们想为单身人士编写单元测试:
void test_singleton() {
Singleton s; // Problem 1
s.do_something();
assert(/* some post-condition */);
}
和依赖类:
struct StubSingleton : Singleton // Problem 2
{
int did_something;
StubSingleton : did_something(0) {}
void do_something() {++did_something;}
};
void test_dependent() {
StubSingleton s; // Problem 1
Dependent d(s); // Problem 3
d.do_something_else();
assert(s.did_something == 1);
}
我们认为有三个问题需要克服:
克服这些问题的最简单方法是重构单例类:
所以现在我们的课程看起来像:
class Singleton {
public:
virtual ~Singleton() {}
virtual void do_something() = 0;
};
class RealSingleton : public Singleton
{
void do_something();
};
class Dependent {
public:
explicit Dependent(Singleton & s) : s(s) {}
void do_something_else();
private:
Singleton & s;
};
现在该类很容易测试,并且几乎同样易于在生产中使用(您只需要创建RealSingleton
的实例并在需要的地方传递对它的引用)。唯一的问题是你不能再把它称为单身。
答案 2 :(得分:1)
我就是这样做的
class Singleton
{
protected:
static Singleton *instance = 0:
public:
Singleton &GetInstance()
{
if (!instance) instance = new Singleton;
return *instance;
}
...
};
然后测试我会创建仅用于测试目的
class TestSingleton : public Singleton
{
public:
void DestroyInstance() {
if (instance) delete instance;
instance = 0;
};
然后使用TestSingleton - 这样您就可以执行所有测试用例并确保重新创建实例的开始。
答案 3 :(得分:0)
单身只是一个只能有一个实例的类。如何找到该实例不是该模式的一部分,因此将DI与单例一起使用是完全正确的。
对单例模式进行单元测试很难,这是反对使用它的主要论据之一。在C ++中实现它的一种方法是在单独的编译单元中定义单例,以便在测试使用单例的类时可以链接到模拟实现。