/* DEPEND4TEST.hpp - inject test mock singletons and dependencies Copyright (C) Lumiera.org 2013, Hermann Vosseler This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef LIB_TEST_DEPEND_4TEST_H #define LIB_TEST_DEPEND_4TEST_H #include "lib/depend.hpp" #include "lib/meta/duck-detector.hpp" #include #include #include namespace lib { namespace test{ namespace { ///< details: inject a mock automatically in place of a singleton using boost::enable_if; using lib::meta::Yes_t; using lib::meta::No_t; /** * Metafunction: does the Type in question * give us a clue about what service interface to use? */ template class defines_ServiceInterface { META_DETECT_NESTED (ServiceInterface); public: enum{ value = HasNested_ServiceInterface::value }; }; /** * Policy-Trait: determine the access point to install the mock. * @note either the mock service implementation needs to provide * explicitly a typedef for the ServiceInterface, or we're * just creating a separate new instance of the singleton service, * while shadowing (but not destroying) the original instance. */ template struct ServiceInterface { typedef I Type; }; template struct ServiceInterface >::type> { typedef typename MOCK::ServiceInterface Type; }; }//(End) mock injection details /** * Scoped object for installing/deinstalling a mocked service automatically. * Placing a suitably specialised instance of this template into a local scope * will inject the corresponding mock installation and remove it when the * control flow leaves this scope. * @param TYPE the concrete mock implementation type to inject. It needs to * be default constructible. If TYPE is a subclass of the service interface, * it needs to expose a typedef \c ServiceInterface */ template struct Depend4Test : boost::noncopyable { typedef typename ServiceInterface::Type Interface; boost::scoped_ptr mock_; Interface* shadowedOriginal_; Depend4Test() : mock_(new TYPE) , shadowedOriginal_(Depend::injectReplacement (mock_.get())) { } ~Depend4Test() { ENSURE (mock_); Depend::injectReplacement (shadowedOriginal_); } }; }} // namespace lib::test #endif