Gerald
Gerald

Reputation: 23499

Self-hosting MVC6 app

I'm trying to get an MVC6 app to be self-hosted for testing. I can do in-memory testing using TestServer, but for testing integration of multiple web apps, one of which includes a middleware that I have no control over that connects to the other app, I need at least one of the apps to be accessible over TCP.

I have tried using WebApp.Start, but it works with an IAppBuilder rather than IApplicationBuilder, so I can't get it to work with my Startup.

Is there any way to get an MVC6 app to be self-hosted in an xUnit test, via OWIN or any other way?

UPDATE:

FWIW, based on Pinpoint's answer and some additional research, I was able to come up with the following base class that works in xUnit, at least when the tests are in the same project as the MVC project:

public class WebTestBase : IDisposable
{
    private IDisposable webHost;

    public WebTestBase()
    {
        var env = CallContextServiceLocator.Locator.ServiceProvider.GetRequiredService<IApplicationEnvironment>();
        var builder = new ConfigurationBuilder(env.ApplicationBasePath)
            .AddIniFile("hosting.ini");

        var config = builder.Build();

        webHost = new WebHostBuilder(CallContextServiceLocator.Locator.ServiceProvider, config)
            .UseEnvironment("Development")
            .UseServer("Microsoft.AspNet.Server.WebListener")
            .Build()
            .Start();
    }
    public void Dispose()
    {
        webHost.Dispose();
    }
}

Upvotes: 2

Views: 1661

Answers (2)

K&#233;vin Chalet
K&#233;vin Chalet

Reputation: 42120

Katana's WebApp static class has been replaced by WebHostBuilder, that offers a much more flexible approach: https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/WebHostBuilder.cs.

You've probably already used this API without realizing it, as it's the component used by the hosting block when you register a new web command in your project.json (e.g Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:54540) and run it using dnx (e.g dnx . web):

namespace Microsoft.AspNet.Hosting
{
    public class Program
    {
        private const string HostingIniFile = "Microsoft.AspNet.Hosting.ini";
        private const string ConfigFileKey = "config";

        private readonly IServiceProvider _serviceProvider;

        public Program(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public void Main(string[] args)
        {
            // Allow the location of the ini file to be specified via a --config command line arg
            var tempBuilder = new ConfigurationBuilder().AddCommandLine(args);
            var tempConfig = tempBuilder.Build();
            var configFilePath = tempConfig[ConfigFileKey] ?? HostingIniFile;

            var appBasePath = _serviceProvider.GetRequiredService<IApplicationEnvironment>().ApplicationBasePath;
            var builder = new ConfigurationBuilder(appBasePath);
            builder.AddIniFile(configFilePath, optional: true);
            builder.AddEnvironmentVariables();
            builder.AddCommandLine(args);
            var config = builder.Build();

            var host = new WebHostBuilder(_serviceProvider, config).Build();
            using (host.Start())
            {
                Console.WriteLine("Started");
                var appShutdownService = host.ApplicationServices.GetRequiredService<IApplicationShutdown>();
                Console.CancelKeyPress += (sender, eventArgs) =>
                {
                    appShutdownService.RequestShutdown();
                    // Don't terminate the process immediately, wait for the Main thread to exit gracefully.
                    eventArgs.Cancel = true;
                };
                appShutdownService.ShutdownRequested.WaitHandle.WaitOne();
            }
        }
    }
}

https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/Program.cs

Upvotes: 1

John Davidson
John Davidson

Reputation: 635

You can use Microsoft.AspNet.TestHost

See http://www.strathweb.com/2015/05/integration-testing-asp-net-5-asp-net-mvc-6-applications/ for details on use.

TestHost can work with your startup using a line like

        TestServer dataServer = new TestServer(TestServer.CreateBuilder().UseStartup<WebData.Startup>()); 

where is the name of the application. The application has to be referenced in the test harness

Upvotes: 0

Related Questions