4

I need to do integration tests on an ASP.Net MVC controller that calls HttpContext.Current in each of it's methods. I have tried various approaches and done plenty of research already, although I feel like there is something i am missing. I have gone the routes of:

  • Asp.Net core: I had found a hack on stack overflow using asp.net core test host courtesy of Stefan Steiger (How to get HttpContext.Current in ASP.NET Core?). This is a great solution. However, upon an attempt at implementation and further reading, it appears that this will only work with an aspnetcore controller and is not backward compatible. I am aware of a shim however I cannot find any instruction on how to use it.
  • Spinning up iis express using a batch file and making the calls. The issue i got with this approach is that i need to be able to debug in the tests. I tried attaching the visual studio debugger however this was for some reason not working. I kept getting the message on the breakpoint "The breakpoint will not currently be hit. No symbols have been loaded for this document".
  • I've also researched how to launch the project with the test controller programmatically but could not find how to launch a visual studio web project programmatically. (looked in to launching it via a process and msbuild)
  • Currently i am testing using owin self host, however, the HttpContext.Current is null in the controller (obviously). If there is a way around this, it is the most preferable method.

Any advice on how to get these tests done would be greatly appreciated.

Thanks,

Edit, I am attaching using the following method:

 private static bool AttachToIIS(int tries = 10, int threadsleep = 500)
    {
        System.Threading.Thread.Sleep(1000);
        bool isAttached = false;
        int count = 0;
        while (isAttached == false && count < tries)
        {
            _DTE dte = (_DTE)Marshal.GetActiveObject("VisualStudio.DTE.14.0");
            Processes processes = dte.ActiveWindow.DTE.Debugger.LocalProcesses;
            foreach (EnvDTE.Process process in processes)
            {
                System.Diagnostics.Debug.WriteLine("process: " + process.Name);
                try
                {
                    if (process.Name.Contains("iis"))
                    {
                        process.Attach();
                        isAttached = true;
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.Message);
                }
            }
            System.Threading.Thread.Sleep(threadsleep);
            count++;
        }
        return isAttached;
    }

The one oddity is that when i attach to the debugger (I am no COM expert), it attaches the debugger of the visual studio instance that was opened first.

Community
  • 1
  • 1
mattylantz
  • 312
  • 4
  • 10
  • Update: I went the route of spinning up iis express and attaching the debugger. The trick was to run iis on one thread and the request on another thread; the controller is hit and debuggable and the httpcontext.current is not null. However, this only happens if iis is running previous to the test being ran. So, when i run it without iis already running, the breakpoint in the controller is not hit, however it is hit when the test is run with iis previously running. I'm sure this has something to do with processes. – mattylantz Dec 08 '16 at 14:42
  • Update: I am just spinning up iis express in the background and keeping it running; then calling out to the server in the unit tests. The one oddity is that when i attach to the debugger (I am no COM expert), it attaches the debugger of the visual studio instance that was opened first. – mattylantz Dec 13 '16 at 16:22

1 Answers1

0

Depending on why you use HttpContext.Current, you could modify your code to use the HttpContext property of the Controller class instead.

Then you can create a custom ControllerContext for your tests that can contain an HTTP context as well. Note that MVC is more intelligent than the old ASP.NET because it uses HttpContextBase which you can inherit and even mock a completely custom HTTP context in your tests.

Relevant links:

Community
  • 1
  • 1
Venemo
  • 18,515
  • 13
  • 84
  • 125
  • Thanks, we ended up just altering the controller endpoint, using an ioc container to inject a 'shim' implementation of an interface that returns the test version of an IHttpContextManager (which returns an HttpContext) when testing, and the actual Current HttpContext when run. Thanks again!!! – mattylantz May 26 '17 at 05:17