Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to Mock out time in a unit test?

Following on from this question...I'm trying to unit test the following scenario:

I have a class that allows one to call a method to perform some action and if it fails wait a second and recall that method.

Say I wanted to call a method DoSomething()...but in the event of an exception being thrown by DoSomething() I want to be able to retry calling it up to a maximum of 3 times but wait 1 second between each attempt. The aim of the unit test, in this case, is to verify that when we called DoSomething() 3 times with 1 second waits between each retry that the total time taken is >= 3 seconds.

Unfortunately, the only way I can think to test it, is to time it using a Stopwatch....which has two side effects...

  1. it takes 3 seconds to execute the test...and I usually like my tests to run in milliseconds
  2. the amount of time to run the test varies by +/- 10ms or so which can cause the test to fail unless I take this variance into account.

What would be nice is if there were a way to mock out this dependency on time so that my test is able to run quicker and be fairly consistent in it's results. Unfortunately, I can't think of a way to do so...and so I thought I'd ask and see if any of you out there have ever encountered this problem...

like image 886
mezoid Avatar asked Dec 04 '22 14:12

mezoid


1 Answers

You could make a Waiter class who provides a method, Wait(int) that waits the amount of time specified. Make tests for this method, then in your unit test, pass in a mocked up version that simply keeps track of how long it was asked to wait, but returns immediately.

For instance (C#):

interface IWaiter
{
    void Wait(int milliseconds);
}

class Waiter : IWaiter
{
    public void Wait(int milliseconds)
    {
        // not accurate, but for the sake of simplicity:
        Thread.Sleep(milliseconds);
    }
}

class MockedWaiter : IWaiter
{
    public void Wait(int milliseconds)
    {
        WaitedTime += milliseconds;
    }
    public int WaitedTime { get; private set; }
}
like image 158
Matthew Scharley Avatar answered Jan 03 '23 09:01

Matthew Scharley