¿Alguien me puede ayudar a explicar cómo TimeProvider.Current
puede ser nulo en la siguiente clase?¿Cómo puede ser que este contexto ambiental se vuelva nulo?
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;
}
}
Observaciones
- todas las pruebas unitarias que hacen referencia directamente TimeProvider también invoca ResetToDefault() en su Fixture desmontaje.
- Hay no código multiproceso involucrado.
- De vez en cuando, una de las pruebas de unidad falla porque
TimeProvider.Current
es nulo (se lanza NullReferenceException). - Esto solo ocurre cuando ejecuto todo el paquete, pero no cuando solo realizo una prueba unitaria, lo que me sugiere que hay una sutil interdependencia de prueba.
- Sucede aproximadamente una vez cada cinco o seis ejecuciones de prueba.
- Cuando ocurre una falla, parece estar ocurriendo en las primeras pruebas ejecutadas que involucran
TimeProvider.Current
. - Más de una prueba puede fallar, pero solo una falla en una ejecución de prueba determinada.
Fwiw, aquí está la clase DefaultTimeProvider así:
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; }
}
}
sospecho que hay algo sutil interacción pasando con la inicialización estática, donde la duración es de hecho permitió acceder a la TimeProvider.Current
antes de toda la inicialización estática ha terminado, pero no puedo entenderlo.
Cualquier ayuda es apreciada.
Fwiw Me acaba de lanzar
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
en el captador, y constantemente informa el mismo ID para todos los casos de prueba en una prueba de funcionamiento, por lo que el problema no parece estar relacionada con el roscado.
qué ocurre también si se utiliza un constructor estático en lugar de inicialización campo estático? En el DefaultTimeProvider que es. – asgerhallas
Sí, lo hace ... –
Puse esto en mi blog, ya que estaba teniendo algunos problemas para encontrar detalles del contexto ambiental - espero que no te importe: http://relentlessdevelopment.wordpress.com/2013/09/30/testing-datetimes-and-other-things-with-an-ambient-context/ –