Can anyone help me explain how TimeProvider.Current
can become null in the following class?
public abstract class TimeProvider
{
private static TimeProvider current =
DefaultTimeProvider.Instance;
public static TimeProvider Current
{
get { return TimeProvider.current; }
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
TimeProvider.current = value;
}
}
public abstract DateTime UtcNow { get; }
public static void ResetToDefault()
{
TimeProvider.current = DefaultTimeProvider.Instance;
}
}
Observations
- All unit tests that directly reference TimeProvider also invokes ResetToDefault() in their Fixture Teardown.
- There is no multithreaded code involved.
- Once in a while, one of the unit tests fail because
TimeProvider.Current
is null (NullReferenceException is thrown). - This only happens when I run the entire suite, but not when I just run a single unit test, suggesting to me that there is some subtle test interdependence going on.
- It happens approximately once every five or six test runs.
- When a failure occurs, it seems to be occuring in the first executed tests that involves
TimeProvider.Current
. - More than one test can fail, but only one fails in a given test run.
FWIW, here's the DefaultTimeProvider class as well:
public class DefaultTimeProvider : TimeProvider
{
private readonly static DefaultTimeProvider instance =
new DefaultTimeProvider();
private DefaultTimeProvider() { }
public override DateTime UtcNow
{
get { return DateTime.UtcNow; }
}
public static DefaultTimeProvider Instance
{
get { return DefaultTimeProvider.instance; }
}
}
I suspect that there's some subtle interplay going on with static initialization where the runtime is actually allowed to access TimeProvider.Current
before all static initialization has finished, but I can't quite put my finger on it.
Any help is appreciated.
FWIW I just threw
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
in the getter, and it consistently reports the same ID for all test cases in a test run, so the issue seems not related to threading.