Может ли кто-нибудь помочь мне объяснить, как TimeProvider.Current
может стать нулевым в следующем классе?
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;
}
}
Наблюдения
- Все модульные тесты, которые напрямую ссылаются на TimeProvider, также вызывают ResetToDefault () в своем процессе разрушения Fixture.
- В нет многопоточного кода.
- Время от времени один из модульных тестов не выполняется, поскольку
TimeProvider.Current
имеет значение null (выбрасывается исключение NullReferenceException).
- Это происходит только тогда, когда я запускаю весь пакет, но не тогда, когда я просто запускаю одиночный модульный тест, что наводит меня на мысль, что происходит некоторая тонкая взаимозависимость теста.
- Это происходит примерно раз в пять или шесть тестовых прогонов.
- Когда происходит сбой, кажется, что это происходит в первых выполненных тестах, которые включают
TimeProvider.Current
.
- Более одного теста может быть неудачным, но только один не пройден в данном тестовом прогоне.
FWIW, вот класс DefaultTimeProvider:
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; }
}
}
Я подозреваю, что есть некоторая тонкая взаимосвязь, происходящая со статической инициализацией, когда среде выполнения действительно разрешен доступ к TimeProvider.Current
до того, как вся статическая инициализация завершена, но я не могу понять, как это сделать.
Любая помощь приветствуется.
FWIW Я только что бросил
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
в получателе, и он последовательно сообщает один и тот же идентификатор для всех тестовых случаев в тестовом прогоне, поэтому проблема, похоже, не связана с многопоточностью.