How can this Ambient Context become null?
- by Mark Seemann
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.