Info
-
Did you know about gtest.gmock mocking framework?
Example
#include <gmock/gmock.h>
struct mock {
MOCK_METHOD(void, on, (int));
};
int main() {
StrictMock<mock> mock{};
EXPECT_CALL(mock, on(42));
mock.on(43); // failure : Unexpected mock function call
}
Puzzle
-
Can you implement generic-strict
mock_on
for on calls with given types...?- Note: Inheritance from
StrictMock<T>
for eachT
inTEvents
is required
- Note: Inheritance from
template<class... TEvents>
struct mock_on; // TODO
template<class T>
class foo {
public:
explicit(true) foo(const T& t) : t_{t} { }
auto run(const auto& event) const -> void {
t_.on(event);
}
private:
const T& t_;
};
int main() {
struct event1 { constexpr auto operator<=>(const event1&) const = default; } event1;
struct event2 { constexpr auto operator<=>(const event2&) const = default; } event2;
struct event3 { constexpr auto operator<=>(const event3&) const = default; } event3;
"mock single event"_test = [&] {
mock_on<decltype(event1)> mock{};
foo foo{mock};
EXPECT_CALL(mock, on(event1));
foo.run(event1);
};
"mock mutliple events"_test = [&] {
mock_on<decltype(event1), decltype(event2), decltype(event3)> mock{};
foo foo{mock};
EXPECT_CALL(mock, on(event1));
EXPECT_CALL(mock, on(event2));
EXPECT_CALL(mock, on(event3));
foo.run(event1);
foo.run(event2);
foo.run(event3);
};
}
Solutions
template<typename TEvent>
struct mock_on_impl
{
MOCK_METHOD(void, on, (TEvent), (const));
};
template<typename...TEvents>
struct mock_on : mock_on_impl<TEvents>...
{
using mock_on_impl<TEvents>::gmock_on...;
using mock_on_impl<TEvents>::on...;
};
template <class TEvent>
struct mock_on_impl {
MOCK_METHOD(void, on, (TEvent), (const));
};
} // namespace detail
template <class... TEvents>
struct mock_on : testing::StrictMock<detail::mock_on_impl<TEvents>>... {
using detail::mock_on_impl<TEvents>::on...;
using detail::mock_on_impl<TEvents>::gmock_on...;
};
namespace detail {
template <class TEvent>
struct mock {
MOCK_METHOD(void, on, (const TEvent&), (const));
};
}
template <class... TEvents>
struct mock_on : ::testing::StrictMock<detail::mock<TEvents>>... {
using ::testing::StrictMock<detail::mock<TEvents>>::on...;
using ::testing::StrictMock<detail::mock<TEvents>>::gmock_on...;
};
template <class TEvent>
struct on_impl {
MOCK_METHOD(void, on, (const TEvent&), (const));
};
template <class... TEvents>
struct mock_on : testing::StrictMock<on_impl<TEvents>>... {
using testing::StrictMock<on_impl<TEvents>>::on...;
using testing::StrictMock<on_impl<TEvents>>::gmock_on...;
};
template<int N> struct None{};
template<class TEvent1, class TEvent2 = None<0> , class TEvent3 = None<1> >
struct mock_on {
MOCK_METHOD(void, on, (TEvent1), (const));
MOCK_METHOD(void, on, (TEvent2), (const));
MOCK_METHOD(void, on, (TEvent3), (const));
};
template<class TEvent>
struct mock{
MOCK_METHOD(void, on, (const TEvent&), (const));
};
template<class... TEvents>
struct mock_on : ::testing::StrictMock<mock<TEvents>>...{
using ::testing::StrictMock<mock<TEvents>>::on...;
using ::testing::StrictMock<mock<TEvents>>::gmock_on...;
};