0

Edit: I have classes that receives messages:

class Foo {
public:
    void receive(FooMessage& message));
    // other messages
}
class Bar {
public:
    void receive(BarMessage& message));
    // other messages
}

and mock that test receiving those messages:

class Mock {
public:
    MOCK_METHOD(void, receive, (FooMessage& arg));
    MOCK_METHOD(void, receive, (BarMessage& arg));
    // a lot other messages
}

I wanted to turn Mock into template, so instead of writing long list of MOCK_METHOD() in Mock I would create mock like this:

Mock<BarMessage,BazMessage> myMock;

and have those mock methods generated for me. Is it possible to achieve?


Original question: I have mock class that looks like this:

class foo
{
public:
    MOCK_METHOD(void, foo, (bar& arg));
    MOCK_METHOD(void, foo, (bar& arg));
    // other overloads
}

Is it possible to create those mock methods using template parameter pack? I'm looking to do something like this:

template <typename...Ts>
class foo
{
public:
    template <Ts...t>
    MOCK_METHOD(void, foo, (t& arg))...;
}
  • references to `bar` and `baz` – WBurzynski Jul 30 '21 at 09:08
  • MOCK_METHOD is a complex macro, I think your approach is not practical. We may consider to define macros to call MOCK_METHOD – prehistoricpenguin Jul 30 '21 at 09:15
  • @JeJo I edited question, hopefully now it's clear. – WBurzynski Jul 30 '21 at 09:48
  • @WBurzynski Added an example of Boost Preprocessor for your particular example. Not sure if you have seen that before accepting my answer! – 2b-t Jul 30 '21 at 12:13
  • The only workaround I can see to the Boost.PP answer is to declare a single `MOCK_METHOD(void, foo, std::variant)` and see if that works. I'm not offering it as an answer, because I haven't tested whether it actually behaves - but it's worth a try if you have C++17 (or access to a Boost, experimental or TR variant) – Useless Jul 30 '21 at 12:27
  • @Useless This works only partially. Calls to mock method are registered as expected, but unfortunately matchers don't work. Maybe with some clever conversion or custom matchers i could make this work. – WBurzynski Aug 02 '21 at 09:37

1 Answers1

1

No, this is not possible, at least not in the way sketched out by you above with variadic templates. gMock is based on macros which in C++ are expanded by the pre-processor before compilation, so before variadic macros are considered.

The only chance you have of achieving something like this is by writing a macro of your own similar to this which iterates over the elements of a variadic macro or using the Boost Preprocessor library that contains powerful macros such as BOOST_PP_SEQ_FOR_EACH. With the latter you could define a macro with arguments

#define RECEIVE_MOCK_METHOD(R, DATA, ELEM) MOCK_METHOD(void, receive, (ELEM& arg));

and then call it with Boost Preprocessor like

BOOST_PP_SEQ_FOR_EACH(RECEIVE_MOCK_METHOD, , (FooMessage) (BarMessage) (BazMessage))

resulting in three mock methods

MOCK_METHOD(void, receive, (FooMessage& arg));
MOCK_METHOD(void, receive, (BarMessage& arg));
MOCK_METHOD(void, receive, (BazMessage& arg));

Try it here!

2b-t
  • 2,153
  • 1
  • 7
  • 16