Adding tests for convention-based routing

This commit is contained in:
Ryan Nowak 2014-06-23 11:12:32 -07:00
parent 3aae5cb4fa
commit f194723230
10 changed files with 345 additions and 2 deletions

15
Mvc.sln
View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.21806.0
VisualStudioVersion = 14.0.21727.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
EndProject
@ -45,6 +45,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AutofacWebSite", "test\WebS
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.TestConfiguration", "test\WebSites\Microsoft.AspNet.Mvc.TestConfiguration\Microsoft.AspNet.Mvc.TestConfiguration.kproj", "{680D75ED-601F-4D86-B01B-1072D0C31B8C}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RoutingWebSite", "test\WebSites\RoutingWebSite\RoutingWebSite.kproj", "{42CDBF4A-E238-4C0F-A416-44588363EB4C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -225,6 +227,16 @@ Global
{680D75ED-601F-4D86-B01B-1072D0C31B8C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{680D75ED-601F-4D86-B01B-1072D0C31B8C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{680D75ED-601F-4D86-B01B-1072D0C31B8C}.Release|x86.ActiveCfg = Release|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Debug|x86.ActiveCfg = Debug|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Any CPU.Build.0 = Release|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{42CDBF4A-E238-4C0F-A416-44588363EB4C}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -248,5 +260,6 @@ Global
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{07C0E921-FCBB-458C-AC11-3D01CE68B16B} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{680D75ED-601F-4D86-B01B-1072D0C31B8C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{42CDBF4A-E238-4C0F-A416-44588363EB4C} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
EndGlobalSection
EndGlobal

View File

@ -33,6 +33,7 @@
<Compile Include="ActivatorTests.cs" />
<Compile Include="DependencyResolverTests.cs" />
<Compile Include="InlineConstraintTests.cs" />
<Compile Include="RoutingTests.cs" />
<Compile Include="TestAssemblyProvider.cs" />
<Compile Include="TestConfigurationProvider.cs" />
<Compile Include="TestHelper.cs" />
@ -42,4 +43,4 @@
<Compile Include="TestApplicationEnvironment.cs" />
</ItemGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>
</Project>

View File

@ -0,0 +1,151 @@
// 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.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
{
public class RoutingTests
{
private readonly IServiceProvider _services;
private readonly Action<IBuilder> _app = new RoutingWebSite.Startup().Configure;
public RoutingTests()
{
_services = TestHelper.CreateServices("RoutingWebSite");
}
[Fact]
public async Task ConventionRoutedController_ActionIsReachable()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.Handler;
// Act
var response = await client.GetAsync("http://localhost/Home/Index");
// Assert
Assert.Equal(200, response.StatusCode);
var body = await response.ReadBodyAsStringAsync();
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
Assert.Contains("/Home/Index", result.ExpectedUrls);
Assert.Equal("Home", result.Controller);
Assert.Equal("Index", result.Action);
Assert.Equal(
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
{
{ "controller", "Home" },
{ "action", "Index" },
},
result.RouteValues);
}
[Fact]
public async Task ConventionRoutedController_ActionIsReachable_WithDefaults()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.Handler;
// Act
var response = await client.GetAsync("http://localhost/");
// Assert
Assert.Equal(200, response.StatusCode);
var body = await response.ReadBodyAsStringAsync();
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
Assert.Contains("/", result.ExpectedUrls);
Assert.Equal("Home", result.Controller);
Assert.Equal("Index", result.Action);
Assert.Equal(
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
{
{ "controller", "Home" },
{ "action", "Index" },
},
result.RouteValues);
}
[Fact]
public async Task ConventionRoutedController_NonActionIsNotReachable()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.Handler;
// Act
var response = await client.GetAsync("http://localhost/Home/NotAnAction");
// Assert
Assert.Equal(404, response.StatusCode);
}
[Fact]
public async Task ConventionRoutedController_InArea_ActionIsReachable()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.Handler;
// Act
var response = await client.GetAsync("http://localhost/Travel/Flight/Index");
// Assert
Assert.Equal(200, response.StatusCode);
var body = await response.ReadBodyAsStringAsync();
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
Assert.Contains("/Travel/Flight/Index", result.ExpectedUrls);
Assert.Equal("Flight", result.Controller);
Assert.Equal("Index", result.Action);
Assert.Equal(
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
{
{ "area", "Travel" },
{ "controller", "Flight" },
{ "action", "Index" },
},
result.RouteValues);
}
[Fact]
public async Task ConventionRoutedController_InArea_ActionBlockedByHttpMethod()
{
// Arrange
var server = TestServer.Create(_services, _app);
var client = server.Handler;
// Act
var response = await client.GetAsync("http://localhost/Travel/Flight/BuyTickets");
// Assert
Assert.Equal(404, response.StatusCode);
}
// See TestResponseGenerator in RoutingWebSite for the code that generates this data.
private class RoutingResult
{
public string[] ExpectedUrls { get; set; }
public string ActualUrl { get; set; }
public Dictionary<string, object> RouteValues { get; set; }
public string Action { get; set; }
public string Controller { get; set; }
}
}
}

View File

@ -12,6 +12,7 @@
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-*",
"Microsoft.Framework.DependencyInjection": "1.0.0-*",
"Microsoft.Framework.Runtime.Interfaces": "1.0.0-*",
"RoutingWebSite": "",
"Xunit.KRunner": "1.0.0-*"
},
"commands": {

View File

@ -0,0 +1,28 @@
using Microsoft.AspNet.Mvc;
using System;
namespace RoutingWebSite
{
// This controller is reachable via traditional routing.
[Area("Travel")]
public class FlightController
{
private readonly TestResponseGenerator _generator;
public FlightController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult Index()
{
return _generator.Generate("/Travel/Flight", "/Travel/Flight/Index");
}
[HttpPost]
public IActionResult BuyTickets()
{
return _generator.Generate("/Travel/Flight/BuyTickets");
}
}
}

View File

@ -0,0 +1,28 @@
// 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 Microsoft.AspNet.Mvc;
namespace RoutingWebSite
{
// This controller is reachable via traditional routing.
public class HomeController : Controller
{
private readonly TestResponseGenerator _generator;
public HomeController(TestResponseGenerator generator)
{
_generator = generator;
}
public IActionResult Index()
{
return _generator.Generate("/", "/Home", "/Home/Index");
}
public IActionResult About()
{
return _generator.Generate();
}
}
}

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>42cdbf4a-e238-4c0f-a416-44588363eb4c</ProjectGuid>
<OutputType>Web</OutputType>
</PropertyGroup>
<PropertyGroup Condition="$(OutputType) == 'Console'">
<DebuggerFlavor>ConsoleDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="$(OutputType) == 'Web'">
<DebuggerFlavor>WebDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" Label="Configuration">
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DevelopmentServerPort>11178</DevelopmentServerPort>
</PropertyGroup>
<ItemGroup>
<Compile Include="Areas\Travel\FlightController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Startup.cs" />
<Compile Include="TestResponseGenerator.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="project.json" />
</ItemGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@ -0,0 +1,33 @@
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Routing;
using Microsoft.Framework.ConfigurationModel;
using Microsoft.Framework.DependencyInjection;
namespace RoutingWebSite
{
public class Startup
{
public void Configure(IBuilder app)
{
var configuration = app.GetTestConfiguration();
app.UseServices(services =>
{
services.AddMvc(configuration);
services.AddScoped<TestResponseGenerator>();
});
app.UseMvc(routes =>
{
routes.MapRoute("areaRoute",
"{area:exists}/{controller}/{action}",
new { controller = "Home", action = "Index" });
routes.MapRoute("ActionAsMethod", "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" });
});
}
}
}

View File

@ -0,0 +1,37 @@
// 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 Microsoft.AspNet.Mvc;
using Microsoft.Framework.DependencyInjection;
namespace RoutingWebSite
{
// Generates a response based on the expected URL and action context
public class TestResponseGenerator
{
private readonly ActionContext _actionContext;
public TestResponseGenerator(IContextAccessor<ActionContext> contextAccessor)
{
_actionContext = contextAccessor.Value;
if (_actionContext == null)
{
throw new InvalidOperationException("ActionContext should not be null here.");
}
}
public JsonResult Generate(params string[] expectedUrls)
{
return new JsonResult(new
{
expectedUrls = expectedUrls,
actualUrl = _actionContext.HttpContext.Request.Path.Value,
routeValues = _actionContext.RouteData.Values,
action = _actionContext.ActionDescriptor.Name,
controller = ((ReflectedActionDescriptor)_actionContext.ActionDescriptor).ControllerDescriptor.Name,
});
}
}
}

View File

@ -0,0 +1,11 @@
{
"dependencies": {
"Helios": "1.0.0-*",
"Microsoft.AspNet.Mvc": "",
"Microsoft.AspNet.Mvc.TestConfiguration": ""
},
"configurations": {
"net45": { },
"k10": { }
}
}