diff --git a/global.json b/global.json index b90c8282a0..897f517580 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,3 @@ { - "sources": ["src", "test\\WebSites"] + "sources": ["src", "test\\WebSites", "samples"] } \ No newline at end of file diff --git a/samples/MvcSample.Web/Startup.cs b/samples/MvcSample.Web/Startup.cs index ea107cac99..acaa3b103a 100644 --- a/samples/MvcSample.Web/Startup.cs +++ b/samples/MvcSample.Web/Startup.cs @@ -1,5 +1,6 @@ using System; using Microsoft.AspNet.Builder; +using Microsoft.AspNet.Mvc; using Microsoft.AspNet.Routing; using Microsoft.Framework.ConfigurationModel; using Microsoft.Framework.DependencyInjection; @@ -21,12 +22,11 @@ public void Configure(IBuilder app) app.UseFileServer(); #if ASPNET50 var configuration = new Configuration() - .AddJsonFile(@"App_Data\config.json") - .AddEnvironmentVariables(); - + .AddJsonFile(@"App_Data\config.json") + .AddEnvironmentVariables(); string diSystem; - if (configuration.TryGet("DependencyInjection", out diSystem) && + if (configuration.TryGet("DependencyInjection", out diSystem) && diSystem.Equals("AutoFac", StringComparison.OrdinalIgnoreCase)) { app.UseMiddleware(); @@ -36,8 +36,12 @@ public void Configure(IBuilder app) services.AddMvc(); services.AddSingleton(); services.AddSingleton(); - services.AddTransient(); + services.AddTransient(); services.Add(OptionsServices.GetDefaultServices()); + // Setup services with a test AssemblyProvider so that only the + // sample's assemblies are loaded. This prevents loading controllers from other assemblies + // when the sample is used in the Functional Tests. + services.AddTransient>(); // Create the autofac container ContainerBuilder builder = new ContainerBuilder(); @@ -63,6 +67,10 @@ public void Configure(IBuilder app) services.AddSingleton(); services.AddSingleton(); services.AddTransient(); + // Setup services with a test AssemblyProvider so that only the + // sample's assemblies are loaded. This prevents loading controllers from other assemblies + // when the sample is used in the Functional Tests. + services.AddTransient>(); }); } diff --git a/samples/MvcSample.Web/TestAssemblyProvider.cs b/samples/MvcSample.Web/TestAssemblyProvider.cs new file mode 100644 index 0000000000..b1db4925f5 --- /dev/null +++ b/samples/MvcSample.Web/TestAssemblyProvider.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Reflection; +using Microsoft.AspNet.Mvc; + +namespace MvcSample.Web +{ + /// + /// Limits MVC to use a single Assembly for controller discovery. + /// This is used by the functional test to limit the Controller discovery to + /// MvcSample.Web Assembly alone. + /// The sample should work in the absense of this file. + /// + /// + /// This is a generic type because it needs to instantiated by a service provider to replace + /// a built-in MVC service. + /// + public class TestAssemblyProvider : IControllerAssemblyProvider + { + public TestAssemblyProvider() + { + CandidateAssemblies = new Assembly[] { typeof(T).GetTypeInfo().Assembly }; + } + + public IEnumerable CandidateAssemblies { get; private set; } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcSampleTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcSampleTests.cs new file mode 100644 index 0000000000..01a66c402c --- /dev/null +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/MvcSampleTests.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.TestHost; +using Xunit; + +namespace Microsoft.AspNet.Mvc.FunctionalTests +{ + public class MvcSampleTests + { + // Path relative to Mvc\\test\Microsoft.AspNet.Mvc.FunctionalTests + private readonly IServiceProvider _services = + TestHelper.CreateServices("MvcSample.Web", Path.Combine("..", "..", "samples")); + private readonly Action _app = new MvcSample.Web.Startup().Configure; + + [Fact] + public async Task Home_Index_ReturnsSuccess() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/Home/Index"); + + // Assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + } + + [Fact] + public async Task Home_NotFoundAction_Returns404() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/Home/NotFound"); + + // Assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); + } + + [Fact] + public async Task Home_CreateUser_ReturnsXmlBasedOnAcceptHeader() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Home/ReturnUser"); + request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/xml;charset=utf-8")); + + // Act + var response = await client.SendAsync(request); + + // Assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("I like playing Football" + + "
My address
13true" + + "
Dependents address
0false" + + "0Dependents name" + + "13.37" + + "My nameSecure stringSoftware Engineer
", + new StreamReader(await response.Content.ReadAsStreamAsync(), Encoding.UTF8).ReadToEnd()); + } + + [Theory] + [InlineData("http://localhost/Filters/ChallengeUser", HttpStatusCode.Unauthorized)] + [InlineData("http://localhost/Filters/AllGranted", HttpStatusCode.Unauthorized)] + [InlineData("http://localhost/Filters/NotGrantedClaim", HttpStatusCode.Unauthorized)] + public async Task FiltersController_Tests(string url, HttpStatusCode statusCode) + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync(url); + + // Assert + Assert.NotNull(response); + Assert.Equal(statusCode, response.StatusCode); + } + + [Fact] + public async Task FiltersController_Crash_ThrowsException() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/Filters/Crash?message=HelloWorld"); + + // Assert + Assert.NotNull(response); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("Boom HelloWorld", + new StreamReader(await response.Content.ReadAsStreamAsync(), Encoding.UTF8).ReadToEnd()); + } + } +} \ No newline at end of file diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs index 4d719252c7..ec59194d90 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/TestHelper.cs @@ -4,24 +4,25 @@ using System; using System.IO; using System.Reflection; -using System.Threading.Tasks; -using InlineConstraints; -using Microsoft.AspNet.Builder; -using Microsoft.AspNet.Routing; -using Microsoft.AspNet.TestHost; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection.Fallback; +using Microsoft.Framework.Logging; using Microsoft.Framework.Runtime; using Microsoft.Framework.Runtime.Infrastructure; -using Xunit; -using Microsoft.Framework.ConfigurationModel; -using Microsoft.Framework.Logging; namespace Microsoft.AspNet.Mvc.FunctionalTests { public static class TestHelper { + // Path from Mvc\\test\\Microsoft.AspNet.Mvc.FunctionalTests + private static readonly string WebsitesDirectoryPath = Path.Combine("..", "websites"); + public static IServiceProvider CreateServices(string applicationWebSiteName) + { + return CreateServices(applicationWebSiteName, WebsitesDirectoryPath); + } + + public static IServiceProvider CreateServices(string applicationWebSiteName, string applicationPath) { var originalProvider = CallContextServiceLocator.Locator.ServiceProvider; var appEnvironment = originalProvider.GetService(); @@ -33,7 +34,8 @@ public static IServiceProvider CreateServices(string applicationWebSiteName) // To compensate for this, we need to calculate the original path and override the application // environment value so that components like the view engine work properly in the context of the // test. - var appBasePath = CalculateApplicationBasePath(appEnvironment, applicationWebSiteName); + var appBasePath = CalculateApplicationBasePath(appEnvironment, applicationWebSiteName, applicationPath); + var services = new ServiceCollection(); services.AddInstance( typeof(IApplicationEnvironment), @@ -56,21 +58,18 @@ public static IServiceProvider CreateServices(string applicationWebSiteName) typeof(ILoggerFactory), NullLoggerFactory.Instance); - return services.BuildServiceProvider(originalProvider); + var tempServiceProvider = services.BuildServiceProvider(originalProvider); + CallContextServiceLocator.Locator.ServiceProvider = tempServiceProvider; + return tempServiceProvider; } // Calculate the path relative to the application base path. public static string CalculateApplicationBasePath(IApplicationEnvironment appEnvironment, - string applicationWebSiteName) + string applicationWebSiteName, string websitePath) { - // Mvc/test/Microsoft.AspNet.Mvc.FunctionalTests - var appBase = appEnvironment.ApplicationBasePath; - - // Mvc/test - var test = Path.GetDirectoryName(appBase); - // Mvc/test/WebSites/applicationWebSiteName - return Path.GetFullPath(Path.Combine(appBase, "..", "WebSites", applicationWebSiteName)); + return Path.GetFullPath( + Path.Combine(appEnvironment.ApplicationBasePath, websitePath, applicationWebSiteName)); } private static Type CreateAssemblyProviderType(string siteName) diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json b/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json index 3798a68b7e..17561a23d1 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/project.json @@ -21,6 +21,7 @@ "Microsoft.Framework.Runtime.Interfaces": "1.0.0-*", "Microsoft.AspNet.PipelineCore": "1.0.0-*", "ModelBindingWebSite": "", + "MvcSample.Web": "", "RoutingWebSite": "", "RazorWebSite": "", "ValueProvidersSite": "",