Reputation: 73
I am using Hippomocks and have a class that implements an generic interface. When I place expectations on this class I do not get the expected behaviour.
This is my minimum "working" example
template <class T>
struct Foo {
virtual ~Foo() = default;
virtual void bar(const T& t) = 0;
};
struct Baz : public Foo<int>, public Foo<double> {
void bar(const int& t) override = 0;
void bar(const double& t) override = 0;
};
TEST_CASE("Foo")
{
MockRepository mocks;
auto baz = mocks.Mock<Baz>();
mocks.ExpectCall(baz, Foo<int>::bar);
baz->bar(12);
mocks.ExpectCall(baz, Foo<double>::bar);
baz->bar(234.3);
}
I am expecting this test to pass without any problems. However the test fails with the following message (slightly edited to remove project names):
test_foo.cpp|28| FAILED:
|| due to unexpected exception with message:
|| Function called without expectation!
|| Expectations set:
|| test_foo.cpp(31)
|| : Expectation for Foo<int>::bar(...) on the mock at 0x0x5569df8f3400 was
|| satisfied.
|| test_foo.cpp(34)
|| : Expectation for Foo<double>::bar(...) on the mock at 0x0x5569df8f3400 was
|| not satisfied.
I am expecting the bar() belonging to Foo<double> to be invoked.
Upvotes: 1
Views: 653
Reputation: 73
Hippomocks takes care of the case in which there are overloaded class functions.
The expectations I should have used are the following
mocks.ExpectCallOverload(baz, static_cast<void (Baz::*)(const int&)>(&Baz::bar));
baz->bar(12);
mocks.ExpectCallOverload(baz, static_cast<void (Baz::*)(const double&)>(&Baz::bar));
baz->bar(234.3);
The syntax is horrible, but this now behaves as expected.
I should have RTFM...
Upvotes: 0
Reputation: 37485
I was curious how Mock
could be possibly implemented without manually defining all the methods (like other mocking libraries do), but it turns out that it does not work. Mock
implementation employs Undefined Behavior because it just reinterpret_cast
unrelated class to Baz
:
template <typename base>
base *MockRepository::Mock() {
mock<base> *m = new mock<base>(this);
mocks.push_back(m);
return reinterpret_cast<base *>(m);
}
It does various other cheesy things, such as messing with vtable. None of that stuff can work reliably.
Upvotes: 1