How did I do?*

Assert DateTime.Now/UtcNow equality with xUnit

When comparing DateTime.Now or DateTime.UtcNow values in tests, you've likely encountered failures due to these lines of code executing at different times, and the values therefore differing by a few milliseconds.

Technically they are different and should fail, however for testing purposes, unless absolute accuracy is required, it's useful to permit a small margin of error to account for test execution delays.

The example below will fail because now1 is defined prior to action execution, and this date will therefore be slightly earlier than the new instance of UtcNow in the "expected" value in the assertion:

[Fact]
public async Task DatesAreEqual()
{
    // Arrange
    var now1 = DateTime.UtcNow;

    // Act
    var result = _myService.SetCreatedDate(now1);

    // Assert
    Assert.Equal(DateTime.UtcNow, result.CreatedDate);
}

Although in this example you're more likely to assert equality between now1 and result.CreatedDate to make sure SetCreatedDate is setting the date correctly, this is purely to illustrate the issue.

xUnit includes an overload for DateTime assertions with a third parameter in the form of a TimeSpan instance. The example below allows for a one second margin of error:

Assert.Equal(DateTime.UtcNow, result.CreatedDate, TimeSpan.FromSeconds(1));

Depending on the duration or complexity of your test, you may want to increase this margin of error to a few more seconds, or even use FromMinutes for larger resource-intensive integration tests. If you use the same margin of error across multiple tests, it may be useful to define it as a private field:

private readonly TimeSpan _marginOfError = TimeSpan.FromSeconds(1);

Note: This overload expects a non-nullable DateTime. If either of the comparison values are nullable, you'll need to reference it's Value, and/or use the null forgiving operator.

Assert.Equal(now1, result.CreatedDate!.Value, _marginOfError);