Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autofac OWIN TestServer and HttpContext

I am trying to setup Integration tests with my IIS Hosted WebAPI 2.2 application. I use Autofac for DI and I am using the new ASP.net Identity stack which uses OWIN. I am running into an issue with Autofac where the HttpContext class is always null. Here is how I am setting up my base integration test class-

 [TestClass]
public class TestBase
{
    private SimpleLifetimeScopeProvider _scopeProvider;
    private IDependencyResolver _originalResolver;
    private HttpConfiguration _configuration;
    public TestServer Server { get; private set; }

    [TestInitialize]
    public void Setup()
    {
        Server = TestServer.Create(app =>
        {
            //config webpai
            _configuration = new HttpConfiguration();
            WebApiConfig.Register(_configuration);

            // Build the container.
            var container = App_Start.IocConfig.RegisterDependencies(_configuration);
            _scopeProvider = new SimpleLifetimeScopeProvider(container);

            //set the mvc dep resolver
            var mvcResolver = new AutofacDependencyResolver(container, _scopeProvider);
            _originalResolver = DependencyResolver.Current;
            DependencyResolver.SetResolver(mvcResolver);

            //set the webapi dep resolvers
            _configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);

            app.UseAutofacMiddleware(container);
            app.UseAutofacWebApi(_configuration);
            app.UseAutofacMvc();
        });
    }

    [TestCleanup]
    public void Cleanup()
    {
        // Clean up the fake 'request' scope.
        _configuration.Dispose();
        DependencyResolver.SetResolver(_originalResolver);
        _scopeProvider.EndLifetimeScope();
        Server.Dispose();
    }
}

When a simple test starts, I get an ArgumentNullException "Value cannot be null" httpContext. Which if I track down into the autofac code, I think it is coming from this extension method -

 public static class AutofacMvcAppBuilderExtensions
    {
        internal static Func<HttpContextBase> CurrentHttpContext = () => new HttpContextWrapper(HttpContext.Current);

        /// <summary>
        /// Extends the Autofac lifetime scope added from the OWIN pipeline through to the MVC request lifetime scope.
        /// </summary>
        /// <param name="app">The application builder.</param>
        /// <returns>The application builder.</returns>
        [SecuritySafeCritical]
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
        public static IAppBuilder UseAutofacMvc(this IAppBuilder app)
        {
            return app.Use(async (context, next) =>
            {
                var lifetimeScope = context.GetAutofacLifetimeScope();
                var httpContext = CurrentHttpContext();

                if (lifetimeScope != null && httpContext != null)
                    httpContext.Items[typeof(ILifetimeScope)] = lifetimeScope;

                await next();
            });
        }
    }

loacted in the Core/Source/Autofac.Integration.Mvc.Owin/AutofacMvcAppBuilderExtensions.cs file. Is there a problem with my setup, or a proper way to use Autofac in integration tests with a WebApi application using IIS Host and OWIN Middleware?

like image 257
thebringking Avatar asked Feb 12 '23 18:02

thebringking


1 Answers

It appears you already asked this as an issue over on the Autofac project. I'll copy/paste the answer here (though in the future it'd probably be better to go with one or the other and not both).

Part of the awesomeness of OWIN-only apps is that you don't need HttpContext anymore. Nothing is tied to that; instead, it's all HttpContextBase and things that are separate from the legacy IIS. Like, in Web API, the current context is always shipped around with the HttpRequestMessage - there's no global static HttpContext.Current because that's legacy stuff.

Thus, when you run unit tests with an OWIN test host, you can expect there to not be an HttpContext.Current. It's decoupled from all that.

MVC can't run as OWIN-only because the libraries are tightly coupled to the legacy IIS/ASP.NET stack. Trying to test MVC stuff using an OWIN-only test server is going to give you trouble like this. That will change with the new ASP.NET 5.0 coming out with the new Visual Studio.

If you need to test MVC in an integrated way, there isn't a way to do that with OWIN right now. You have to fire up IIS Express.

Finally, I do see that you're missing the Web API middleware for OWIN (the actual Microsoft Web API middleware). That might give you other problems down the line.

app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(_configuration);
app.UseAutofacMvc();
// You're missing this:
app.UseWebApi(config);
like image 61
Travis Illig Avatar answered Mar 28 '23 06:03

Travis Illig