mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Documented limitation concerning MOCK_METHOD_TPL
This commit is contained in:
parent
712653eb99
commit
12a252a850
5 changed files with 142 additions and 16 deletions
|
|
@ -13,6 +13,7 @@ Not yet released
|
|||
* Dropped support for obsolete Boost.Phoenix V2
|
||||
* Added support for multiple parameters constraints
|
||||
* Added inline to generated MOCK_FUNCTION
|
||||
* Documented limitation concerning MOCK_METHOD_TPL
|
||||
|
||||
[section 1.2.6]
|
||||
Released 24 May 2014
|
||||
|
|
|
|||
78
doc/example/limitations_template_base_class_method.cpp
Normal file
78
doc/example/limitations_template_base_class_method.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// http://turtle.sourceforge.net
|
||||
//
|
||||
// Copyright Mathieu Champlon 2014
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#define BOOST_AUTO_TEST_MAIN
|
||||
#include <boost/test/auto_unit_test.hpp>
|
||||
#include <turtle/mock.hpp>
|
||||
|
||||
namespace limitations_template_base_class_method_problem
|
||||
{
|
||||
//[ limitations_template_base_class_method_problem
|
||||
template< typename T >
|
||||
class base
|
||||
{
|
||||
public:
|
||||
virtual ~base()
|
||||
{}
|
||||
|
||||
virtual void method() = 0;
|
||||
};
|
||||
//]
|
||||
|
||||
//[ limitations_template_base_class_method_solution
|
||||
template< typename T >
|
||||
MOCK_BASE_CLASS( mock_base, base< T > )
|
||||
{
|
||||
MOCK_METHOD( method, 1, void() )
|
||||
};
|
||||
//]
|
||||
}
|
||||
|
||||
namespace limitations_template_base_class_method_problem_2
|
||||
{
|
||||
//[ limitations_template_base_class_method_problem_2
|
||||
class concept
|
||||
{
|
||||
public:
|
||||
template< typename T >
|
||||
T create()
|
||||
{
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
void function_under_test( T t ) // T is supposed to model the previous concept
|
||||
{
|
||||
t.template create< int >();
|
||||
t.template create< std::string >();
|
||||
}
|
||||
//]
|
||||
|
||||
//[ limitations_template_base_class_method_solution_2
|
||||
MOCK_CLASS( mock_concept )
|
||||
{
|
||||
template< typename T >
|
||||
T create();
|
||||
|
||||
MOCK_METHOD( create_int, 0, int(), create_int )
|
||||
MOCK_METHOD( create_string, 0, std::string(), create_string )
|
||||
};
|
||||
|
||||
template<>
|
||||
int mock_concept::create< int >()
|
||||
{
|
||||
return create_int();
|
||||
}
|
||||
template<>
|
||||
std::string mock_concept::create< std::string >()
|
||||
{
|
||||
return create_string();
|
||||
}
|
||||
//]
|
||||
}
|
||||
|
|
@ -53,6 +53,22 @@ or with C++11 nullptr support :
|
|||
|
||||
[endsect]
|
||||
|
||||
[section Non-virtual methods cannot be mocked]
|
||||
|
||||
Given :
|
||||
|
||||
[limitations_non_virtual_method_problem]
|
||||
|
||||
the following code compiles but will not work as expected :
|
||||
|
||||
[limitations_non_virtual_method_problem_2]
|
||||
|
||||
The mock object will never be exercised because the library relies on polymorphism to hook the calls.
|
||||
|
||||
There is no other solution than to refactor the production code, the most simple being to change the method to virtual.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Template methods cannot be mocked]
|
||||
|
||||
Given :
|
||||
|
|
@ -75,23 +91,27 @@ While still somewhat possible, mocking a template method can indeed prove a bit
|
|||
|
||||
[endsect]
|
||||
|
||||
[section Non-virtual methods cannot be mocked]
|
||||
[section Template base class methods cannot be mocked without specifying the signature]
|
||||
|
||||
Given :
|
||||
|
||||
[limitations_non_virtual_method_problem]
|
||||
[limitations_template_base_class_method_problem]
|
||||
|
||||
the following code compiles but will not work as expected :
|
||||
the following code does not compile :
|
||||
|
||||
[limitations_non_virtual_method_problem_2]
|
||||
template< typename T >
|
||||
MOCK_BASE_CLASS( mock_base, base< T > )
|
||||
{
|
||||
MOCK_METHOD( method, 0 ) // this fails
|
||||
};
|
||||
|
||||
The mock object will never be exercised because the library relies on polymorphism to hook the calls.
|
||||
A workaround would be to add the signature to MOCK_METHOD :
|
||||
|
||||
There is no other solution than to refactor the production code, the most simple being to change the method to virtual.
|
||||
[limitations_template_base_class_method_solution]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section Private virtual methods cannot be mocked without spelling out the signature]
|
||||
[section Private virtual methods cannot be mocked without specifying the signature]
|
||||
|
||||
Given :
|
||||
|
||||
|
|
@ -101,7 +121,7 @@ the following code does not compile :
|
|||
|
||||
MOCK_BASE_CLASS( mock_base, base )
|
||||
{
|
||||
MOCK_METHOD( method, 0 ) // this fails because 'method' is not visible
|
||||
MOCK_METHOD( method, 0 ) // this fails because 'method' is not visible
|
||||
};
|
||||
|
||||
A workaround would be to add the signature to MOCK_METHOD :
|
||||
|
|
@ -120,7 +140,7 @@ the following code does not compile :
|
|||
|
||||
MOCK_BASE_CLASS( mock_class, base_class )
|
||||
{
|
||||
MOCK_METHOD( method, 0 ) // this fails because of the throw specifier
|
||||
MOCK_METHOD( method, 0 ) // this fails because of the throw specifier
|
||||
};
|
||||
|
||||
A workaround would be to write a proxy member function :
|
||||
|
|
|
|||
|
|
@ -87,18 +87,20 @@ Deriving from mock::object is optional but provides the additional following ben
|
|||
|
||||
Synopsis :
|
||||
|
||||
MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates both const and non-const methods
|
||||
MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the const version of the method
|
||||
MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the non-const version of the method
|
||||
MOCK_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates both const and non-const methods
|
||||
MOCK_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the const version of the method
|
||||
MOCK_NON_CONST_METHOD( [calling convention] name, arity[, signature[, identifier]] ) // generates only the non-const version of the method
|
||||
|
||||
MOCK_METHOD_TPL( [calling convention] name, arity[, signature[, identifier]] ) // must be used if the signature uses a template parameter of the class, generates both const and non-const methods
|
||||
MOCK_CONST_METHOD_TPL( [calling convention] name, arity[, signature[, identifier]] ) // must be used if the signature uses a template parameter of the class, generates only the const version of the method
|
||||
MOCK_NON_CONST_METHOD_TPL( [calling convention] name, arity[, signature[, identifier]] ) // must be used if the signature uses a template parameter of the class, generates only the non-const version of the method
|
||||
MOCK_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, generates both const and non-const methods
|
||||
MOCK_CONST_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, generates only the const version of the method
|
||||
MOCK_NON_CONST_METHOD_TPL( [calling convention] name, arity, signature[, identifier] ) // must be used if the signature uses a template parameter of the class, generates only the non-const version of the method
|
||||
|
||||
[note If the identifier is omitted it will default to the method name.]
|
||||
|
||||
[note If the method name is not ambiguous both the signature and the identifier can be omitted in the context of a derived MOCK_BASE_CLASS or base_type typedef.]
|
||||
|
||||
[note The signature cannot be omitted for the _TPL familly of macros, see the related [link turtle.limitations.template_base_class_methods_cannot_be_mocked_without_specifying_the_signature limitation section].]
|
||||
|
||||
[note The signature must be surrounded with round parenthesis if the return type contains a comma.]
|
||||
|
||||
[note [link turtle.reference.creation.constructor Constructors], [link turtle.reference.creation.destructor destructors] and [link turtle.reference.creation.conversion_operator conversion operators] require special care.]
|
||||
|
|
|
|||
|
|
@ -378,8 +378,9 @@ namespace
|
|||
};
|
||||
|
||||
template< typename T >
|
||||
MOCK_CLASS( variadic_tpl )
|
||||
MOCK_BASE_CLASS( variadic_tpl, base )
|
||||
{
|
||||
MOCK_METHOD( m1, 0 )
|
||||
MOCK_METHOD_TPL( m2, 0, T() )
|
||||
MOCK_METHOD_TPL( m3, 0, T(), m3 )
|
||||
MOCK_CONST_METHOD_TPL( m4, 0, T() )
|
||||
|
|
@ -400,6 +401,30 @@ namespace
|
|||
MOCK_FUNCTOR( f_variadic, std::map< int, int >() );
|
||||
}
|
||||
|
||||
#else // MOCK_VARIADIC_MACROS
|
||||
|
||||
namespace
|
||||
{
|
||||
struct base
|
||||
{
|
||||
virtual ~base()
|
||||
{}
|
||||
protected:
|
||||
virtual void m1() = 0;
|
||||
};
|
||||
|
||||
MOCK_BASE_CLASS( derived, base )
|
||||
{
|
||||
MOCK_METHOD( m1, 0 )
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
MOCK_BASE_CLASS( derived_tpl, base )
|
||||
{
|
||||
MOCK_METHOD( m1, 0 )
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MOCK_VARIADIC_MACROS
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue