c++googlemock

GMOCK a method accepting variable arguments


I have a class that has a method which accepts variable arguments:

class MyClass
{
public:
virtual void myprint(const char* format, ...) = 0; 
};

I was trying to mock the above class

class Mock : public MyClass
{
public:
MOCK_METHOD1(myprint, void (const char* format, ...));
}

But it gives my compilation issues:

error: 'Result' in 'struct testing::internal::Function<void(const char*, ...)>' does not name a type
  MOCK_METHOD1(myprint, void (const char* format, ...));
  ^
error: incomplete type 'testing::internal::Function<void(const char*, ...)>' used in nested name specifier
 error: incomplete type 'testing::internal::Function<void(const char*, ...)>' used in nested name specifier
error: template argument 1 is invalid
error: field 'gmock1_print_15' has incomplete type 'testing::internal::FunctionMocker<void(const char*, ...)>'

How can I mock a method that takes variable arguments as a parameter?


Solution

  • Unfortunately, you cannot directly mock a variadic function in Gmock:

    You cannot mock a variadic function (i.e. a function taking ellipsis (...) arguments) directly in Google Mock.

    The problem is that in general, there is no way for a mock object to know how many arguments are passed to the variadic method, and what the arguments' types are. Only the author of the base class knows the protocol, and we cannot look into his head.

    Therefore, to mock such a function, the user must teach the mock object how to figure out the number of arguments and their types. One way to do it is to provide overloaded versions of the function.

    Ellipsis arguments are inherited from C and not really a C++ feature. They are unsafe to use and don't work with arguments that have constructors or destructors. Therefore we recommend to avoid them in C++ as much as possible.

    However, Nemelis on SO has suggested some workaround that you could use to achieve this. It involves processing your format argument along with any variadic arguments to create a single message string, and then mocking a function that takes in message as a single argument.