All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonar.plugins.csharp.S6354.html Maven / Gradle / Ivy

There is a newer version: 10.2.0.105762
Show newest version

Why is this an issue?

One of the principles of a unit test is that it must have full control of the system under test. This is problematic when production code includes calls to static methods, which cannot be changed or controlled. Date/time functions are usually provided by system libraries as static methods.

This can be improved by wrapping the system calls in an object or service that can be controlled inside the unit test.

Noncompliant code example

public class Foo
{
    public string HelloTime() =>
        $"Hello at {DateTime.UtcNow}";
}

Compliant solution

There are different approaches to solve this problem. One of them is suggested below. There are also open source libraries (such as NodaTime) which already implement an IClock interface and a FakeClock testing class.

public interface IClock
{
    DateTime UtcNow();
}

public class Foo
{
    public string HelloTime(IClock clock) =>
        $"Hello at {clock.UtcNow()}";
}

public class FooTest
{
    public record TestClock(DateTime now) : IClock
    {
        public DateTime UtcNow() => now;
    }

    [Fact]
    public void HelloTime_Gives_CorrectTime()
    {
        var dateTime = new DateTime(2017, 06, 11);
        Assert.Equal((new Foo()).HelloTime(new TestClock(dateTime)), $"Hello at {dateTime}");
    }
}

Another possible solution is using an adaptable static class, ideally supports an IDisposable method, that not only adjusts the time behaviour for the current thread only, but also for scope of the using.

public static class Clock
{
    public static DateTime UtcNow() { /* ... */ }
    public static IDisposable SetTimeForCurrentThread(Func<DateTime> time) { /* ... */ }
}

public class Foo
{
    public string HelloTime() =>
        $"Hello at {Clock.UtcNow()}";
}

public class FooTest
{
    [Fact]
    public void HelloTime_Gives_CorrectTime()
    {
        var dateTime = new DateTime(2017, 06, 11);
        using (Clock.SetTimeForCurrentThread(() => dateTime))
        {
             Assert.Equal((new Foo()).HelloTime(), $"Hello at {dateTime}");
        }
    }
}

Resources

NodaTime testing





© 2015 - 2024 Weber Informatics LLC | Privacy Policy