mirror of
https://github.com/mat007/turtle.git
synced 2026-06-22 12:13:43 +00:00
Merge pull request #8 from mat007/protected-mock-method
Protected mock method
This commit is contained in:
commit
41de7236c4
7 changed files with 188 additions and 33 deletions
|
|
@ -31,7 +31,10 @@
|
|||
<ClCompile Include="..\..\test\test_constraint.cpp" />
|
||||
<ClCompile Include="..\..\test\test_constraints.cpp" />
|
||||
<ClCompile Include="..\..\test\test_exception.cpp" />
|
||||
<ClCompile Include="..\..\test\test_integration.cpp" />
|
||||
<ClCompile Include="..\..\test\test_integration.cpp">
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='release|x64'">BOOST_AUTO_TEST_MAIN;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='debug|x64'">BOOST_AUTO_TEST_MAIN;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\test\test_log.cpp" />
|
||||
<ClCompile Include="..\..\test\test_matcher.cpp" />
|
||||
<ClCompile Include="..\..\test\test_max_args.cpp" />
|
||||
|
|
@ -84,6 +87,22 @@
|
|||
<IntDir Condition="'$(Configuration)|$(Platform)'=='release|Win32'">../../out/vc100/$(Configuration)/tests/$(ProjectName)\</IntDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='release|x64'">../../out/vc100_x64/$(Configuration)/tests/$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
|
||||
<IncludePath>c:\dev\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;</IncludePath>
|
||||
<LibraryPath>c:\dev\lib\vc100_x64;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
|
||||
<IncludePath>c:\dev\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;</IncludePath>
|
||||
<LibraryPath>c:\dev\lib\vc100_x64;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
|
||||
<IncludePath>c:\dev\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;</IncludePath>
|
||||
<LibraryPath>c:\dev\lib\vc100_x64;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSdkDir)lib\x64;</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
|
||||
<IncludePath>c:\dev\include;$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSdkDir)include;$(FrameworkSDKDir)\include;</IncludePath>
|
||||
<LibraryPath>c:\dev\lib\vc100_x64;$(VCInstallDir)lib\amd64;$(VCInstallDir)atlmfc\lib\amd64;$(WindowsSdkDir)lib\x64;</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/Zm172 %(AdditionalOptions)</AdditionalOptions>
|
||||
|
|
@ -145,8 +164,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>cd ../../run/vc100
|
||||
"$(TargetDir)$(TargetName).exe" --result_code=no --report_level=no --log_level=warning --data_directory=../../data/tests/$(ProjectName)
|
||||
<Command>"$(TargetDir)$(TargetName).exe" --result_code=no --report_level=no --log_level=warning --data_directory=../../data/tests/$(ProjectName)
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
|
|
@ -211,8 +229,7 @@
|
|||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>cd ../../run/vc100
|
||||
"$(TargetDir)$(TargetName).exe" --result_code=no --report_level=no --log_level=warning --data_directory=../../data/tests/$(ProjectName)
|
||||
<Command>"$(TargetDir)$(TargetName).exe" --result_code=no --report_level=no --log_level=warning --data_directory=../../data/tests/$(ProjectName)
|
||||
</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@ 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
|
||||
* Fixed mocking protected member function
|
||||
|
||||
[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.]
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@
|
|||
|
||||
#else // MOCK_VARIADIC_MACROS
|
||||
|
||||
#define MOCK_BASE_CLASS(T, I) \
|
||||
struct T : I, mock::object, mock::detail::base< I >
|
||||
#define MOCK_BASE_CLASS(T, B) \
|
||||
struct T : B, mock::object, mock::detail::base< B >
|
||||
|
||||
#define MOCK_FUNCTOR(f, S) \
|
||||
mock::detail::functor< MOCK_FUNCTION_TYPE(S,) > f, f##_mock
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
|
||||
#define MOCK_FUNCTION_AUX(F, n, S, t, s, tpn) \
|
||||
MOCK_FUNCTION_HELPER(S, t, s, tpn) \
|
||||
s MOCK_DECL(F, n, S,,tpn) \
|
||||
s inline MOCK_DECL(F, n, S,,tpn) \
|
||||
{ \
|
||||
BOOST_MPL_ASSERT_RELATION( n, ==, \
|
||||
boost::function_types::function_arity< \
|
||||
|
|
@ -177,29 +177,32 @@
|
|||
#define MOCK_VARIADIC_ELEM_1(e0, e1, ...) e1
|
||||
#define MOCK_VARIADIC_ELEM_2(e0, e1, e2, ...) e2
|
||||
|
||||
#define MOCK_METHOD(M, ... ) \
|
||||
MOCK_METHOD_EXT(M, \
|
||||
#define MOCK_METHOD_SIGNATURE(M, n, S, t) \
|
||||
typedef MOCK_FUNCTION_TYPE(S,) BOOST_PP_CAT(t,_sig_type); \
|
||||
MOCK_METHOD_EXT(M, n, BOOST_PP_CAT(t,_sig_type), t)
|
||||
#define MOCK_METHOD(M, ...) \
|
||||
MOCK_METHOD_SIGNATURE(M, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__ ), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, MOCK_SIGNATURE(M)), \
|
||||
MOCK_VARIADIC_ELEM_2(__VA_ARGS__, M, M))
|
||||
#define MOCK_CONST_METHOD(M, n, ... ) \
|
||||
#define MOCK_CONST_METHOD(M, n, ...) \
|
||||
MOCK_CONST_METHOD_EXT(M, n, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M))
|
||||
#define MOCK_NON_CONST_METHOD(M, n, ... ) \
|
||||
#define MOCK_NON_CONST_METHOD(M, n, ...) \
|
||||
MOCK_NON_CONST_METHOD_EXT(M, n, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M))
|
||||
|
||||
#define MOCK_METHOD_TPL(M, n, ... ) \
|
||||
#define MOCK_METHOD_TPL(M, n, ...) \
|
||||
MOCK_METHOD_EXT_TPL(M, n, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M))
|
||||
#define MOCK_CONST_METHOD_TPL(M, n, ... ) \
|
||||
#define MOCK_CONST_METHOD_TPL(M, n, ...) \
|
||||
MOCK_CONST_METHOD_EXT_TPL(M, n, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M))
|
||||
#define MOCK_NON_CONST_METHOD_TPL(M, n, ... ) \
|
||||
#define MOCK_NON_CONST_METHOD_TPL(M, n, ...) \
|
||||
MOCK_NON_CONST_METHOD_EXT_TPL(M, n, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, M))
|
||||
|
|
@ -212,7 +215,8 @@
|
|||
#define MOCK_STATIC_METHOD(F, n, ...) \
|
||||
MOCK_FUNCTION_AUX(F, n, \
|
||||
MOCK_VARIADIC_ELEM_0(__VA_ARGS__), \
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F), static,)
|
||||
MOCK_VARIADIC_ELEM_1(__VA_ARGS__, F), \
|
||||
static,)
|
||||
|
||||
#define MOCK_STATIC_METHOD_TPL(F, n, ...) \
|
||||
MOCK_FUNCTION_AUX(F, n, \
|
||||
|
|
@ -223,7 +227,8 @@
|
|||
#else // MOCK_VARIADIC_MACROS
|
||||
|
||||
#define MOCK_METHOD(M, n) \
|
||||
MOCK_METHOD_EXT(M, n, MOCK_SIGNATURE(M), M)
|
||||
typedef MOCK_SIGNATURE(M) M##_sig_type; \
|
||||
MOCK_METHOD_EXT(M, n, M##_sig_type, M)
|
||||
|
||||
#define MOCK_FUNCTION(F, n, S, t) \
|
||||
MOCK_FUNCTION_AUX(F, n, S, t,,)
|
||||
|
|
|
|||
|
|
@ -361,6 +361,7 @@ namespace
|
|||
{
|
||||
virtual ~base()
|
||||
{}
|
||||
protected:
|
||||
virtual void m1() = 0;
|
||||
};
|
||||
|
||||
|
|
@ -378,8 +379,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 +402,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
|
||||
|
|
@ -414,6 +440,10 @@ namespace stdcall
|
|||
{
|
||||
struct base
|
||||
{
|
||||
virtual ~base()
|
||||
{}
|
||||
|
||||
protected:
|
||||
virtual void MOCK_STDCALL m1() = 0;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue