Mocking templated functions

7,819 views
Skip to first unread message

Michael Harrington

unread,
Nov 3, 2009, 11:45:44 AM11/3/09
to Google C++ Mocking Framework
Suppose I have a class like this:

struct Foo
{
// ...
template<typename ValueType>
void GetNextValue( const std::string& name, ValueType& value, const
unsigned int streamIndex = 0 )
{
// ...
}
// ...
};

I want to mock calls to GetNextValue, but I'm not sure how to do that
with GoogleMock. I've found several posts on how to mock functions
with default arguments, and how to mock templated /classes/, but none
on how to mock templated /functions/.

Zhanyong Wan (λx.x x)

unread,
Nov 3, 2009, 2:35:53 PM11/3/09
to Michael Harrington, Google C++ Mocking Framework
Hi Michael,

Member function templates cannot be virtual, so you won't be able to
override GetNextValue() in a subclass.

If you want to mock Foo, you must know which value type(s) your tests
are gonna need. Therefore you can add some virtual functions in Foo
to wrap GetNextValue(), such that they can be mocked out:

struct Foo {
...
// This cannot be mocked.
template <typename ValueType>
void GetNextValue(...);

// This can.
virtual void GetNextIntValue(const std::string& name, int& value,
const unsigned int index) {
GetNextValue(name, value, index);
}
...
}


--
Zhanyong

Zhanyong Wan (λx.x x)

unread,
Nov 3, 2009, 4:48:45 PM11/3/09
to Michael Harrington, Google C++ Mocking Framework
(Please keep the mailing list in the loop. Thanks.)

2009/11/3 Michael Harrington <kib...@gmail.com>:
> It's not necessarily a matter of overriding the function. We are using
> policy-based design, so we actually inherit from the mock in order to
> test it rather than pass in a mock derived from a real class -- so the
> mock can be a concrete class of its own and the vtable doesn't even
> matter.
>
> Is it possible to create a mock method that will provide the same
> templated interface to the production code?

Even mock method has some state stored as a member variable of the
mock class. You cannot have member variable templates. Therefore you
cannot have mock method templates.

So my suggestion remains the same (except that the methods don't have
to be virtual). If you want, you can overload the wrappers such that
they share the same name as the template, but I'd avoid that myself.

--
Zhanyong

Michael Harrington

unread,
Nov 4, 2009, 12:31:15 PM11/4/09
to Google C++ Mocking Framework
(Sorry, I hit the wrong reply.)

For posterity, here is the solution I came up with:

(The throws might be a little harsh for the general case, but I know
that, for this mock, any type that I don't expect to be used is an
error.)

struct Foo
{
MOCK_METHOD3(GetNextValueStdString, void(const std::string& name,
std::string& value, const unsigned int streamIndex));

template< typename ValueType >
void GetNextValue( const std::string& name, ValueType& value, const
unsigned int streamIndex )
{
throw "Unexpected call.";
}

template< typename ValueType >
void GetNextValue( const std::string& name, ValueType& value )
{
throw "Unexpected call.";
}

template<>
void GetNextValue< std::string >( const std::string& name,
std::string& value, const unsigned int streamIndex )
{
GetNextValueStdString( name, value, streamIndex );
}

template<>
void GetNextValue< std::string >( const std::string& name,
std::string& value )
{
GetNextValue< std::string >( name, value, 0 );
}
};

On Nov 3, 4:48 pm, Zhanyong Wan (λx.x x) <w...@google.com> wrote:
> (Please keep the mailing list in the loop. Thanks.)
>
> 2009/11/3 Michael Harrington <kibi...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages