2015-02-11 19 views
14

Ho un metodo che utilizza HostingEnvironment.QueueBackgroundWorkItem che desidero unit test alcuni comportamenti prima di questa chiamata, tuttavia, la prova sta venendo a mancare con System.InvalidOperationException : Operation is not valid due to the current state of the object.Mock HostingEnvironment.QueueBackgroundWorkItem in prova xUnit

Ho il sospetto che questo che ho bisogno di prendere in giro il HostingEnvironment ma ignaro di come.

risposta

28

Per risolvere questo problema ho definito un'interfaccia

public interface ITaskScheduler 
{ 
    void QueueBackgroundWorkItem(Action<CancellationToken> workItem); 
} 

Nel codice di produzione inietto attuazione

public class AspNetTaskScheduler : ITaskScheduler 
{ 
    public void QueueBackgroundWorkItem(Action<CancellationToken> workItem) 
    {    
     HostingEnvironment.QueueBackgroundWorkItem(workItem); 
    } 
} 

Nel codice di prova inietto attuazione

public class TaskScheduler : ITaskScheduler 
{ 
    public void QueueBackgroundWorkItem(Action<CancellationToken> workItem) 
    { 
     workItem.Invoke(new CancellationToken()); 
    } 
} 

Credo che questo è un Soluzione OK poiché i test unitari funzionano e le mie classi che accodano le attività in background sono disaccoppiate da HostingEnvironment.

+3

Ecco come dovrebbe essere disaccoppiato d! Dovrebbe essere la risposta accettata! – Mrchief

5

ho finito per fare questo per mantenere le cose semplici:

/// <summary> 
/// add some jobs to the background queue 
/// </summary> 
public static class BackgroundTaskScheduler 
{ 
    /// <summary> 
    /// send the work item to the background queue 
    /// </summary> 
    /// <param name="workItem">work item to enqueue</param> 
    public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem) 
    { 
     try 
     { 
      HostingEnvironment.QueueBackgroundWorkItem(workItem); 
     } 
     catch (InvalidOperationException) 
     { 
      workItem.Invoke(new CancellationToken()); 
     } 
    } 
} 

Poi al fuoco un lavoro semplice:

BackgroundTaskScheduler.QueueBackgroundWorkItem(ct => 
{ 
    // bla 
}); 
1

Un po 'più ordinato di chiamare HostingEnvironment.QueueBackgroundWorkItem indipendentemente dal fatto che c'è un ASP.NET AppDomain quindi catturando il InvalidOperationException è:

public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem) 
{ 
    if (HostingEnvironment.IsHosted) 
    { 
     HostingEnvironment.QueueBackgroundWorkItem(workItem); 
    } 
    else 
    { 
     workItem.Invoke(new CancellationToken()); 
    } 
}