I wanted to use WhenDynamicCastTo<T>(m)
from: https://google.github.io/googletest/reference/matchers.html#pointer-matchers
But the thing I want to dynamic cast is in a shared_ptr
and WhenDynamicCastTo
doesn't work with a smart pointer.
I tried to make my own version that works with smart pointers and I'm not sure how to make a templated matcher, I tried this but it doesn't work:
template <typename To>
MATCHER_P(WhenDynamicPointerCastTo<To>, matcher, "")
{
// Use std::dynamic_pointer_cast here
}
Doing this does work but I'd like to hide it behind a single matcher:
template <typename To>
std::shared_ptr<const To> dynamic_smart_pointer_cast(
const std::shared_ptr<const parent>& p)
{
return std::dynamic_pointer_cast<const To>(p);
}
EXPECT_CALL(*mock_, func(
::testing::ResultOf(
dynamic_smart_pointer_cast<child>,
::testing::Pointee(...))));
I wanted to add an answer as I found a few ways to do it in the end.
I was able to actually use the gmock built in WhenDynamicCastTo
.
The function I was mocking was like:
void func(const std::shared_ptr<interface_type>& i);
When I tried to use WhenDynamicCastTo
like this it was complaining about the type I was casting to being abstract (It had a pure virtual function as well):
EXPECT_CALL(*mock_, func(
::testing::Pointee(::testing::WhenDynamicCastTo<impl>(<do_matching>))));
To make this work with gmocks built in WhenDynamicCastTo
I had to change the template parameter to a reference:
EXPECT_CALL(*mock_, func(
::testing::Pointee(::testing::WhenDynamicCastTo<const impl&>(<do_matching>))));
I was able to make Erik Man's suggesting work with some changes to the template parameters and thought I'd add it incase someone wanted to do something like that:
template <typename To>
class WhenDynamicPointerCastToMatcher
{
public:
explicit WhenDynamicPointerCastToMatcher(
const ::testing::Matcher<std::shared_ptr<To> >& matcher) :
matcher_(matcher)
{
}
void DescribeTo(::std::ostream* os) const
{
GetCastTypeDescription(os);
matcher_.DescribeTo(os);
}
void DescribeNegationTo(::std::ostream* os) const
{
GetCastTypeDescription(os);
matcher_.DescribeNegationTo(os);
}
template <typename From>
bool MatchAndExplain(From from, ::testing::MatchResultListener*) const
{
const std::shared_ptr<To> to{std::dynamic_pointer_cast<To>(from)};
// To-Do: describe failures to the listener
return matcher_.Matches(to);
}
private:
static void GetCastTypeDescription(::std::ostream* os)
{
*os << "when dynamic_pointer_cast";
}
const ::testing::Matcher<std::shared_ptr<To> > matcher_;
};
template <typename To>
inline ::testing::PolymorphicMatcher<WhenDynamicPointerCastToMatcher<To> > WhenDynamicPointerCastTo(
const ::testing::Matcher<std::shared_ptr<To> >& inner_matcher)
{
return ::testing::MakePolymorphicMatcher(
WhenDynamicPointerCastToMatcher<To>(inner_matcher));
}
EXPECT_CALL(*mock_, func(
WhenDynamicPointerCastTo<const impl>(::testing::Pointee(<do_matching>))));