120 lines
3.4 KiB
C++
120 lines
3.4 KiB
C++
/*
|
|
DEPEND4TEST.hpp - inject test mock singletons and dependencies
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
2013, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
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 <boost/scoped_ptr.hpp>
|
|
#include <boost/noncopyable.hpp>
|
|
#include <boost/utility/enable_if.hpp>
|
|
|
|
|
|
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 MOCK>
|
|
class defines_ServiceInterface
|
|
{
|
|
META_DETECT_NESTED (ServiceInterface);
|
|
|
|
public:
|
|
enum{ value = HasNested_ServiceInterface<MOCK>::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<class I, class YES =void>
|
|
struct ServiceInterface
|
|
{
|
|
typedef I Type;
|
|
};
|
|
|
|
|
|
template<class MOCK>
|
|
struct ServiceInterface<MOCK, typename enable_if< defines_ServiceInterface<MOCK> >::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<class TYPE>
|
|
struct Depend4Test
|
|
: boost::noncopyable
|
|
{
|
|
typedef typename ServiceInterface<TYPE>::Type Interface;
|
|
|
|
boost::scoped_ptr<TYPE> mock_;
|
|
Interface* shadowedOriginal_;
|
|
|
|
Depend4Test()
|
|
: mock_(new TYPE)
|
|
, shadowedOriginal_(Depend<Interface>::injectReplacement (mock_.get()))
|
|
{ }
|
|
|
|
~Depend4Test()
|
|
{
|
|
ENSURE (mock_);
|
|
Depend<Interface>::injectReplacement (shadowedOriginal_);
|
|
}
|
|
};
|
|
|
|
|
|
}} // namespace lib::test
|
|
#endif
|