Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QueueBackgroundWorkItem from Microsoft.VisualStudio.TestTools.UnitTesting

I have a Web App that does some processing in the background via QueueBackgroundWorkItem.

I'm wiring up unit tests for functionality in the app and when it attempts to invoke this I get the following error:

System.InvalidOperationException occurred
  HResult=-2146233079
  Message=Operation is not valid due to the current state of the object.
  Source=System.Web
  StackTrace:
       at System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem(Func`2 workItem)

Comparing the environments between when this gets invoked from a unit test vs when it gets invoked as part of a running web server, I see that the AppDomain / HostingEnvironment are different.

Without doing a full web app deployment for testing, is there a way to structure the unit test so that the background work item can run in the proper context?

Preferably without changing the existing target code, just by changing the test code - and if that isn't possible, maybe use IOC to run the background work item in an appropriate background thread depending on its context.

update

This works, although probably there is a more elegant way to do it. Basically only runs it background if invoked from a hosted environment:

private void GetSomeData(SomeCriteria criteria, Dictionary<int, List<Tuple<int, string>>> someParam)
{
    if (System.Web.Hosting.HostingEnvironment.IsHosted)
    {
        System.Web.Hosting.HostingEnvironment.QueueBackgroundWorkItem((token) =>
        {
            GenerateSomeData(token, criteria, someParam);
        });
    }
    else
    {
        CancellationToken token = new CancellationToken();
        GenerateSomeData(token, criteria, someParam);
    }
}
like image 729
dr3x Avatar asked Jan 25 '17 22:01

dr3x


1 Answers

I know it's kinda ugly, but I ended up creating my own helper class

public static class BackgroundWorkItemX
{
    public static void QueueBackgroundWorkItem(Action<CancellationToken> workItem)
    {
        try
        {
            HostingEnvironment.QueueBackgroundWorkItem(workItem);
        }
        catch (InvalidOperationException)
        {
            workItem.Invoke(new CancellationToken());
        }
    }
}

And changed all references to QueueBackgroundWorkItem to this class

like image 180
Alex from Jitbit Avatar answered Nov 19 '22 03:11

Alex from Jitbit