Как я могу сопоставить один элемент из кортежа C++ с помощью gmock?
Как я могу сопоставить один элемент из кортежа C++ с помощью gmock ?
Для примера попробуем извлечь std::string
из std::tuple<std::string, int>
.
Я знаю, что мог бы написать пользовательский сопоставитель следующим образом:
MATCHER_P(match0thOfTuple, expected, "") { return (std::get<0>(arg) == expected); }
Но так как я нашел Pair(m1, m2)
совпадение для std::pair
, я ожидал также найти что-то подобное для 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))));
И делает мой лязг дать ошибку компиляции, как это:
.../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; }
...
Существует ли решение gmock для std::tuple
, аналогичное решению для std::pair
, которое использует сопоставитель gmock Pair
?
1 ответ:
testing::Args
это для упаковки аргументов функции в кортеж-совершенно противоположно тому, чего вы хотите добиться.Мой совет - в вашем случае-распакуйте вещи в макете класса, см.:
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::_));
К сожалению, ни один из текущих сопоставителей 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::_)));