Reputation: 714
I am trying to mock a method Foo::TestTime
that takes a parameter and is called within a separate function. The problem I'm having is the matching of the parameter values.
Bar::Run()
is invoked by the user in the unit test which generates the time
and passes it to Foo::TestTime
, which I need to mock from unit test.
struct Foo
{
virtual void TestTime(long time) {}
};
struct FooMock : public Foo
{
MOCK_METHOD(void, TestTime, (long), (override));
};
class Bar
{
long time{0};
Foo _foo;
public:
Bar(Foo foo) : _foo(foo) {}
void Run()
{
time = GetTime();
_foo.TestTime(time); // mock this function
}
};
How can I match the time
between Bar::Run()
and in unit test MOCK_METHOD
? Is Matcher the way to go?
Full codesample
long GetTime()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
struct Foo
{
virtual void TestTime(long time)
{
}
};
struct FooMock : public Foo
{
MOCK_METHOD(void, TestTime, (long), (override));
};
class Bar
{
long time{0};
Foo _foo;
public:
Bar(Foo foo) : _foo(foo) {}
void Run()
{
time = GetTime();
_foo.TestTime(time); // mock this function
}
};
TEST(UtClass, Test)
{
Foo foo;
FooMock fooMock;
long time = GetTime();
EXPECT_CALL(fooMock, TestTime(time)).WillOnce(testing::Return());
Bar bar{foo};
bar.Run();
}
Upvotes: 0
Views: 481
Reputation: 36
If the point of the test is to make sure that TestTime()
is getting called, then I wouldn't worry about matching the actual value of the time
parameter at all.
Instead you could write you test like this.
EXPECT_CALL(fooMock, TestTime(_));
The _
(or more specifically testing::_
) will match any input given to it.
If you really do need to test what the value of time was, you can either Mock the GetTime()
call or create a fake GetTime()
that allows the test to decide what is returned.
Edit: I looked at the example code you had posted. The reason the test was failing was because the mock object was getting copied when you passed it into Bar's constructor. You were also passing in the foo object. Instead it should pass in the fooMock object.
Updated example link: https://godbolt.org/z/fY5c9qhTf Though I still wouldn't recommend trying to match the time value in the test. Doing so will result in a potentially flaky test.
Upvotes: 1