如何使用 gmock 匹配 C++ 元组中的一个元素?
How can I match one element from a C++ tuple using gmock?
如何使用 gmock 匹配 C++ 元组中的一个元素?
例如,让我们尝试从 std::tuple<std::string, int>
.
中提取 std::string
我知道我可以像这样编写自定义匹配器:
MATCHER_P(match0thOfTuple, expected, "") { return (std::get<0>(arg) == expected); }
但是自从我找到 std::pair
的 Pair(m1, m2)
匹配器后,我希望也能找到 std::tuple
.
的类似匹配器
Gmock Args<N1, N2, ..., Nk>(m)
用于选择元组参数的子集。当仅使用 1 个参数时,它仍然需要一个元组匹配器。以下尝试似乎无法编译:
struct {
MOCK_METHOD1(mockedFunction, void(std::tuple<std::string, int>&));
} mock;
EXPECT_CALL(mock, mockedFunction(testing::Args<0>(testing::Eq(expectedStringValue))));
并让我的 clang 给出这样的编译错误:
.../gtest/googlemock/include/gmock/gmock-matchers.h:204:60: error: invalid operands to binary expression ('const std::__1::tuple<std::__1::basic_string<char> >' and 'const std::__1::basic_string<char>')
bool operator()(const A& a, const B& b) const { return a == b; }
...
std::tuple
是否有类似于 std::pair
的 gmock 解决方案,后者使用 gmock Pair
匹配器?
testing::Args
用于将函数参数打包到元组 - 与您想要实现的完全相反。
我的建议 - 在你的情况下 - 在 Mock class 中解压,参见:
struct mock
{
void mockedFunction(std::tuple<std::string, int>& tt)
{
mockedFunctionUnpacked(std::get<0>(tt), std::get<1>(tt));
}
MOCK_METHOD2(mockedFunctionUnpacked, void(std::string&, int&));
};
然后:
EXPECT_CALL(mock, mockedFunctionUnpacked(expectedStringValue, ::testing::_));
不幸的是,none 当前的 gmock 匹配器适用于 std::tuple 个参数。
如果你想了解 C++ 模板 - 你可以试试这个(不完整 - 只是一个想法如何实现元组匹配的通用功能):
// Needed to use ::testing::Property - no other way to access one
// tuple element as "member function"
template <typename Tuple>
struct TupleView
{
public:
TupleView(Tuple const& tuple) : tuple(tuple) {}
template <std::size_t I>
const typename std::tuple_element<I, Tuple>::type& get() const
{
return std::get<I>(tuple);
}
private:
Tuple const& tuple;
};
// matcher for TupleView as defined above
template <typename Tuple, typename ...M, std::size_t ...I>
auto matchTupleView(M ...m, std::index_sequence<I...>)
{
namespace tst = ::testing;
using TV = TupleView<Tuple>;
return tst::AllOf(tst::Property(&TV::template get<I>, m)...);
}
// Matcher to Tuple - big disadvantage - requires to provide tuple type:
template <typename Tuple, typename ...M>
auto matchTupleElements(M ...m)
{
auto mtv = matchTupleView<Tuple, M...>(m..., std::make_index_sequence<sizeof...(M)>{});
return ::testing::MatcherCast<TupleView<Tuple>>(mtv);
}
然后这样使用:
EXPECT_CALL(mock, mockedFunction(matchTupleElements<std::tuple<std::string, int>>(expectedStringValue, ::testing::_)));
如何使用 gmock 匹配 C++ 元组中的一个元素?
例如,让我们尝试从 std::tuple<std::string, int>
.
std::string
我知道我可以像这样编写自定义匹配器:
MATCHER_P(match0thOfTuple, expected, "") { return (std::get<0>(arg) == expected); }
但是自从我找到 std::pair
的 Pair(m1, m2)
匹配器后,我希望也能找到 std::tuple
.
Gmock Args<N1, N2, ..., Nk>(m)
用于选择元组参数的子集。当仅使用 1 个参数时,它仍然需要一个元组匹配器。以下尝试似乎无法编译:
struct {
MOCK_METHOD1(mockedFunction, void(std::tuple<std::string, int>&));
} mock;
EXPECT_CALL(mock, mockedFunction(testing::Args<0>(testing::Eq(expectedStringValue))));
并让我的 clang 给出这样的编译错误:
.../gtest/googlemock/include/gmock/gmock-matchers.h:204:60: error: invalid operands to binary expression ('const std::__1::tuple<std::__1::basic_string<char> >' and 'const std::__1::basic_string<char>')
bool operator()(const A& a, const B& b) const { return a == b; }
...
std::tuple
是否有类似于 std::pair
的 gmock 解决方案,后者使用 gmock Pair
匹配器?
testing::Args
用于将函数参数打包到元组 - 与您想要实现的完全相反。
我的建议 - 在你的情况下 - 在 Mock class 中解压,参见:
struct mock
{
void mockedFunction(std::tuple<std::string, int>& tt)
{
mockedFunctionUnpacked(std::get<0>(tt), std::get<1>(tt));
}
MOCK_METHOD2(mockedFunctionUnpacked, void(std::string&, int&));
};
然后:
EXPECT_CALL(mock, mockedFunctionUnpacked(expectedStringValue, ::testing::_));
不幸的是,none 当前的 gmock 匹配器适用于 std::tuple 个参数。
如果你想了解 C++ 模板 - 你可以试试这个(不完整 - 只是一个想法如何实现元组匹配的通用功能):
// Needed to use ::testing::Property - no other way to access one
// tuple element as "member function"
template <typename Tuple>
struct TupleView
{
public:
TupleView(Tuple const& tuple) : tuple(tuple) {}
template <std::size_t I>
const typename std::tuple_element<I, Tuple>::type& get() const
{
return std::get<I>(tuple);
}
private:
Tuple const& tuple;
};
// matcher for TupleView as defined above
template <typename Tuple, typename ...M, std::size_t ...I>
auto matchTupleView(M ...m, std::index_sequence<I...>)
{
namespace tst = ::testing;
using TV = TupleView<Tuple>;
return tst::AllOf(tst::Property(&TV::template get<I>, m)...);
}
// Matcher to Tuple - big disadvantage - requires to provide tuple type:
template <typename Tuple, typename ...M>
auto matchTupleElements(M ...m)
{
auto mtv = matchTupleView<Tuple, M...>(m..., std::make_index_sequence<sizeof...(M)>{});
return ::testing::MatcherCast<TupleView<Tuple>>(mtv);
}
然后这样使用:
EXPECT_CALL(mock, mockedFunction(matchTupleElements<std::tuple<std::string, int>>(expectedStringValue, ::testing::_)));