Issue #668: Sample should be covered by a basic functional test.

This commit is contained in:
sornaks 2014-08-22 14:29:41 -07:00
Родитель 34add2249e
Коммит 28e334d3db
6 изменённых файлов: 175 добавлений и 24 удалений

Просмотреть файл

@ -1,3 +1,3 @@
{
"sources": ["src", "test\\WebSites"]
"sources": ["src", "test\\WebSites", "samples"]
}

Просмотреть файл

@ -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 @@ namespace MvcSample.Web
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<MonitoringMiddlware>();
@ -36,8 +36,12 @@ namespace MvcSample.Web
services.AddMvc();
services.AddSingleton<PassThroughAttribute>();
services.AddSingleton<UserNameService>();
services.AddTransient<ITestService, TestService>();
services.AddTransient<ITestService, TestService>();
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<IControllerAssemblyProvider, TestAssemblyProvider<Startup>>();
// Create the autofac container
ContainerBuilder builder = new ContainerBuilder();
@ -63,6 +67,10 @@ namespace MvcSample.Web
services.AddSingleton<PassThroughAttribute>();
services.AddSingleton<UserNameService>();
services.AddTransient<ITestService, TestService>();
// 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<IControllerAssemblyProvider, TestAssemblyProvider<Startup>>();
});
}

Просмотреть файл

@ -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
{
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// This is a generic type because it needs to instantiated by a service provider to replace
/// a built-in MVC service.
/// </remarks>
public class TestAssemblyProvider<T> : IControllerAssemblyProvider
{
public TestAssemblyProvider()
{
CandidateAssemblies = new Assembly[] { typeof(T).GetTypeInfo().Assembly };
}
public IEnumerable<Assembly> CandidateAssemblies { get; private set; }
}
}

Просмотреть файл

@ -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<IBuilder> _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("<User xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=" +
"\"http://schemas.datacontract.org/2004/07/MvcSample.Web.Models\"><About>I like playing Football" +
"</About><Address>My address</Address><Age>13</Age><Alive>true</Alive><Dependent><About i:nil=\"true\" />" +
"<Address>Dependents address</Address><Age>0</Age><Alive>false</Alive><Dependent i:nil=\"true\" />" +
"<GPA>0</GPA><Log i:nil=\"true\" /><Name>Dependents name</Name><Password i:nil=\"true\" />" +
"<Profession i:nil=\"true\" /></Dependent><GPA>13.37</GPA><Log i:nil=\"true\" />" +
"<Name>My name</Name><Password>Secure string</Password><Profession>Software Engineer</Profession></User>",
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());
}
}
}

Просмотреть файл

@ -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<IApplicationEnvironment>();
@ -33,7 +34,8 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// 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 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
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)

Просмотреть файл

@ -21,6 +21,7 @@
"Microsoft.Framework.Runtime.Interfaces": "1.0.0-*",
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
"ModelBindingWebSite": "",
"MvcSample.Web": "",
"RoutingWebSite": "",
"RazorWebSite": "",
"ValueProvidersSite": "",