I'll start with a typical Singleton:
class singleton { public: static singleton & instance(); void f(int value); int g(const std::string & path); private: singleton(); ~singleton(); };
Together with typical piece of client client code that I'm wanting to unit-test:
int client::eg1() { stuff(); more_stuff(); int r = singleton::instance().g("Hello world"); return yet_more_stuff(r); }
My problem is that singleton leads to one or more external dependencies I'd like my unit-tests to bypass. My first step is to create an interface for the singleton:
class singleton_interface { public: virtual void f(int value) = 0; virtual int g(const std::string & path) = 0; ... };
And then make singleton implement the interface. (The saving grace of singleton is that its methods are at least instance methods.)
class singleton : public singleton_interface { public: static singleton & instance(); void f(int value); int g(const std::string & path); private: singleton(); ~singleton(); };
Now I can overload eg1 as follows:
int client::eg1(singleton_interface & instance) { stuff(); more_stuff(); int r = instance.g("Hello world"); return yet_more_stuff(r); } int client::eg1() { return eg1(singleton::instance()); }
And finally, I can create singleton_interface sub-classes and use them in my unit-tests:
struct my_mock_singleton : singleton_interface { explicit my_mock_singleton(int g_result) : g_result(g_result) { } void f(int value) { } int g(const std::string & s) { return g_result; } int g_result; }; void test_client_eg1_hitch_hiker_is_42() { assert(42 == client().eg1(my_mock_singleton(6*9))); }
No comments:
Post a Comment