Mocking clock in C++ unit test
I'm working on a project that does things depend on how much time has elapsed. Specifically for testing purposes, I need to call a method twice a second. The basic idea of the test is something like this: Class c; // Call the do_something() method 2x/second for 5 seconds for( int num_second = 0; num_second < 5; num_second++ ){ c.do_something(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); c.do_something(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } In the do_something() method, we then do some operations based on time, similar to the following pseudo-code: void class::do_something(){ now = create_time_from(std::chrono::system_clock::now()); if( now.second() - last_time.second() >= 1 ){ // The second has rolled over - do some special handling code } // Do something important here last_time = now; } Unfortunately this means that the unit tests can be unreliable, as depending on how loaded the system is the do_something() method may not be called at the correct time, resulting in the special handling code not running. Specifically, since it should be called 2x/second, sometimes it gets called only 1x/second due to delays caused by the sleep. I would like to mock the clock to make this more reliable, but I'm not quite sure how to do it. There are two options that I see: Add in a method to the public API of the class that lets you set the clock. I don't want to do this, since this is required only for tests and adding methods just for tests is generally bad. I could extend the class just for testing, providing a mocked clock for testing somehow. This would potentially involve modifying the public API slightly(for example adding a virtual protected method to get the clock to use). Is there a better way to mock the clock in this case?
I'm working on a project that does things depend on how much time has elapsed. Specifically for testing purposes, I need to call a method twice a second. The basic idea of the test is something like this:
Class c;
// Call the do_something() method 2x/second for 5 seconds
for( int num_second = 0; num_second < 5; num_second++ ){
c.do_something();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
c.do_something();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
In the do_something()
method, we then do some operations based on time, similar to the following pseudo-code:
void class::do_something(){
now = create_time_from(std::chrono::system_clock::now());
if( now.second() - last_time.second() >= 1 ){
// The second has rolled over - do some special handling code
}
// Do something important here
last_time = now;
}
Unfortunately this means that the unit tests can be unreliable, as depending on how loaded the system is the do_something()
method may not be called at the correct time, resulting in the special handling code not running. Specifically, since it should be called 2x/second, sometimes it gets called only 1x/second due to delays caused by the sleep.
I would like to mock the clock to make this more reliable, but I'm not quite sure how to do it. There are two options that I see:
- Add in a method to the public API of the class that lets you set the clock. I don't want to do this, since this is required only for tests and adding methods just for tests is generally bad.
- I could extend the class just for testing, providing a mocked clock for testing somehow. This would potentially involve modifying the public API slightly(for example adding a virtual protected method to get the clock to use).
Is there a better way to mock the clock in this case?