Search code examples
c#xunit.net-5automation-testing

xUnit, using DateTime UtcNow in test fails the with fraction of millisecond


I am working on .NET 5 unit tests for DateTimeUTC. My following tests fails with fraction of millisecond. I am initializing expectedDateTimeUtcNow = DateTimeOffset.UtcNow and then using expectedDateTimeUtcNow to convert to millisecond as SUT to test my method where I pass hardcoded long millisecond value then test pass not sure what I am missing

enter code here

[Fact]
public void ConvertDateTimeToUTC_MustTakeDateTimeParameter_InMilliSecond()
{
        //Arrange
        long startDateTimeUtc = 1626991200000; //2021-07-22 22:00:00
        var expectedDateTime = DateTimeOffset.FromUnixTimeMilliseconds(startDateTimeUtc);

        var expectedDateTimeUtcNow = DateTimeOffset.UtcNow;
        var dateTimeUtcNowMiliSec = expectedDateTimeUtcNow.ToUnixTimeMilliseconds();

        //Act 
        DateTimeOffset utcConvertedDateTime = DateTimeCalculationHelper.ConvertDateTimeToUTC(startDateTimeUtc);
        DateTimeOffset actualDateTimeUtcNow = DateTimeCalculationHelper.ConvertDateTimeToUTC(dateTimeUtcNowMiliSec);


        //Assert
        Assert.Equal(expectedDateTime, utcConvertedDateTime);
        Assert.Equal(expectedDateTimeUtcNow, actualDateTimeUtcNow);
    }

SUT

 public static DateTimeOffset ConvertDateTimeToUTC(long utcDateTimeInMilliSec)
    {
        var dateTimeUtc = DateTimeOffset.FromUnixTimeMilliseconds(utcDateTimeInMilliSec);

        return dateTimeUtc;
    }

Solution

  • Fundamentally, when you convert to a whole number of milliseconds (as you are by calling ToUnixTimeMilliseconds) you lose any sub-millisecond data. This should not be a surprise.

    Currently, your test is somewhat like this:

    double original = 5.5;
    int integer = (int) original;
    double result = (double) integer;
    Assert.Equal(original, result);
    

    If you understand why that test is bound to fail, just apply the same thing to your situation. You can't "regain" the sub-millisecond information that you lost when you convert back to a DateTimeOffset...