0

I have a continuous testing pipeline, where unit and integration tests must pass on PRs before code has been able to merge.

It’s been great at reducing bugs and stabilizing our codebase, but we have a problem with time.

On weekends, several applications that comprise this stack have explicit checks to not let new orders be submitted on weekends. Worse, several of these applications make use of DateTime.Now for these checks and can’t be mocked without a large refactor.

Is it possible within c# to issue a command within our tests that will update the “server time” so most of our tests can work?

PreyZer
  • 51
  • 1
  • 10
Aaron
  • 3
  • 4

2 Answers2

0

Short answer is no. If you want to tweak around some basic interfaces you either need to setup your OS and change time before test runs (which can have very unpredictable results) OR mock it. It is actually very simple:

Instead of using DateTime.Now/UtcNow use your explicit version.

public interface IDateTimeManager
{
    DateTime Now {get;}
}

anywhere in the code base:

var now = _dateTimeManager.Now;

In test setup:

var mockDateTimeManager = new Mock<IDateTimeManager>();
mockDateTimeManager.Setup(x=> x.Now).Returns(new DateTime(2000,1,1));

In di setup:

var container = new Container();
container.RegisterSingleton<IDateTimeManager>(mockDateTimeManager.Object);

If your is app separate executable/service, you can pass an argument which sets initial value of this manager:

myapp.exe --start-date "2000-01-01"

public interface IDateTimeManager
{
    DateTime UtcNow { get; }
}
internal sealed class DateTimeManager : IDateTimeManager
{
    private readonly DateTime _initialTime;
    private readonly DateTime _initialOsTime;
    public DateTime UtcNow => _initialTime + (DateTime.UtcNow - _initialOsTime);

    public DateTimeManager(DateTime initialTime)
    {
        _initialTime = initialTime;
        _initialOsTime = DateTime.UtcNow;

    }
}

PS

Inversion of control is your best friend for those kind of situations.

I come to conclusion it is easier to just replace OS specific methods to my own interfaces, rather than hacking around test environments. For example all of File namespace is often mocked for the same reason in my projects. I can emulate any behavior this way.

eocron
  • 6,885
  • 1
  • 21
  • 50
0

Try this.

To wit, calling the WinAPI function SetSystemTime with the appropriate data structure.

Don't forget to return the server time to "correct"!

[Assuming, of course, your server is Windows, which you don't mention...]

Kevin
  • 398
  • 2
  • 7