How can this Ambient Context become null?

Posted by Mark Seemann on Stack Overflow See other posts from Stack Overflow or by Mark Seemann
Published on 2010-05-15T14:33:51Z Indexed on 2010/05/15 14:44 UTC
Read the original article Hit count: 180

Filed under:
|
|
|
|

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.

© Stack Overflow or respective owner

Related posts about c#

Related posts about unit-testing