Created
January 3, 2012 17:18
-
-
Save ArnisL/1555885 to your computer and use it in GitHub Desktop.
Asp.net mvc route testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Routing{ | |
using Extensions; | |
using Interreg.Web.Controllers; | |
using Xunit; | |
public class ApplicationsFacts:Base{ | |
[Fact] | |
public void Application(){ | |
"~/Applications/1" | |
.ShouldMapTo<ApplicationsController>(c=>c.Application(null,null)); | |
} | |
[Fact] | |
public void ApplicationWithTab(){ | |
"~/Applications/1/Budget" | |
.ShouldMapTo<ApplicationsController>(c=>c.Application(null,"Budget")); | |
} | |
[Fact] | |
public void Register(){ | |
"~/Applications/Register" | |
.ShouldMapTo<ApplicationsController>(c=>c.Register()); | |
} | |
[Fact] | |
public void Download(){ | |
"~/Applications/1/Download" | |
.ShouldMapTo<ApplicationsController>(c=>c.Download(null)); | |
} | |
[Fact] | |
public void Remove(){ | |
"~/Applications/1/Remove" | |
.ShouldMapTo<ApplicationsController>(c=>c.Remove(null)); | |
} | |
[Fact] | |
public void Update(){ | |
"~/Applications/1/Update" | |
.ShouldMapTo<ApplicationsController>(c=>c.Update(null)); | |
} | |
[Fact] | |
public void Withdraw(){ | |
"~/Applications/1/Withdraw" | |
.ShouldMapTo<ApplicationsController>(c=>c.Withdraw(null)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Routing{ | |
using System.Web.Routing; | |
using Interreg.Web.Cfg.Tasks; | |
public class Base{ | |
public Base(){ | |
RouteTable.Routes.Clear(); | |
new RoutingTask().Execute(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Fakes{ | |
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Collections.Specialized; | |
using System.Security.Principal; | |
using System.Web; | |
using System.Web.SessionState; | |
public class FakeHttpContext:HttpContextBase{ | |
private readonly HttpCookieCollection _cookies; | |
private readonly NameValueCollection _formParams; | |
private readonly Dictionary<object,object> _items; | |
private readonly string _method; | |
private readonly NameValueCollection _queryStringParams; | |
private readonly string _relativeUrl; | |
private readonly SessionStateItemCollection _sessionItems; | |
private IPrincipal _principal; | |
private HttpRequestBase _request; | |
private HttpResponseBase _response; | |
public FakeHttpContext(string relativeUrl,string method) | |
:this(relativeUrl,method,null,null,null,null,null) {} | |
public FakeHttpContext(string relativeUrl) | |
:this(relativeUrl,null,null,null,null,null) {} | |
public FakeHttpContext(string relativeUrl,IPrincipal principal,NameValueCollection formParams, | |
NameValueCollection queryStringParams,HttpCookieCollection cookies, | |
SessionStateItemCollection sessionItems) | |
:this(relativeUrl,null,principal,formParams,queryStringParams,cookies,sessionItems) {} | |
public FakeHttpContext(string relativeUrl,string method,IPrincipal principal,NameValueCollection formParams, | |
NameValueCollection queryStringParams,HttpCookieCollection cookies, | |
SessionStateItemCollection sessionItems){ | |
_relativeUrl=relativeUrl; | |
_method=method; | |
_principal=principal; | |
_formParams=formParams; | |
_queryStringParams=queryStringParams; | |
_cookies=cookies; | |
_sessionItems=sessionItems; | |
_items=new Dictionary<object,object>(); | |
} | |
public override HttpRequestBase Request{ | |
get{ | |
return _request?? | |
new FakeHttpRequest(_relativeUrl,_method,_formParams,_queryStringParams,_cookies); | |
} | |
} | |
public override HttpResponseBase Response{ | |
get {return _response??new FakeHttpResponse();} | |
} | |
public override IPrincipal User{ | |
get {return _principal;} | |
set {_principal=value;} | |
} | |
public override HttpSessionStateBase Session{ | |
get {return new FakeHttpSessionState(_sessionItems);} | |
} | |
public override IDictionary Items{ | |
get {return _items;} | |
} | |
public override bool SkipAuthorization{get;set;} | |
public static FakeHttpContext Root(){ | |
return new FakeHttpContext("~/"); | |
} | |
public void SetRequest(HttpRequestBase request){ | |
_request=request; | |
} | |
public void SetResponse(HttpResponseBase response){ | |
_response=response; | |
} | |
public override object GetService(Type serviceType){ | |
return null; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Fakes{ | |
using System; | |
using System.Collections.Specialized; | |
using System.Web; | |
using System.Web.Mvc; | |
public class FakeHttpRequest:HttpRequestBase{ | |
private readonly HttpCookieCollection _cookies; | |
private readonly NameValueCollection _formParams; | |
private readonly string _httpMethod; | |
private readonly NameValueCollection _queryStringParams; | |
private readonly string _relativeUrl; | |
private readonly NameValueCollection _serverVariables; | |
private readonly Uri _url; | |
private readonly Uri _urlReferrer; | |
public FakeHttpRequest(string relativeUrl,string method,NameValueCollection formParams, | |
NameValueCollection queryStringParams, | |
HttpCookieCollection cookies){ | |
_httpMethod=method; | |
_relativeUrl=relativeUrl; | |
_formParams=formParams; | |
_queryStringParams=queryStringParams; | |
_cookies=cookies; | |
_serverVariables=new NameValueCollection(); | |
} | |
public FakeHttpRequest(string relativeUrl,string method,Uri url,Uri urlReferrer,NameValueCollection formParams, | |
NameValueCollection queryStringParams, | |
HttpCookieCollection cookies) | |
:this(relativeUrl,method,formParams,queryStringParams,cookies){ | |
_url=url; | |
_urlReferrer=urlReferrer; | |
} | |
public FakeHttpRequest(string relativeUrl,Uri url,Uri urlReferrer) | |
:this(relativeUrl,HttpVerbs.Get.ToString("g"),url,urlReferrer,null,null,null) {} | |
public override NameValueCollection ServerVariables{ | |
get {return _serverVariables;} | |
} | |
public override NameValueCollection Form{ | |
get {return _formParams;} | |
} | |
public override NameValueCollection QueryString{ | |
get {return _queryStringParams;} | |
} | |
public override HttpCookieCollection Cookies{ | |
get {return _cookies;} | |
} | |
public override string AppRelativeCurrentExecutionFilePath{ | |
get {return _relativeUrl;} | |
} | |
public override Uri Url{ | |
get {return _url;} | |
} | |
public override Uri UrlReferrer{ | |
get {return _urlReferrer;} | |
} | |
public override string PathInfo{ | |
get {return String.Empty;} | |
} | |
public override string ApplicationPath{ | |
get {return "";} | |
} | |
public override string HttpMethod{ | |
get {return _httpMethod;} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Fakes{ | |
using System.Text; | |
using System.Web; | |
public class FakeHttpResponse:HttpResponseBase{ | |
private readonly StringBuilder _outputString=new StringBuilder(); | |
public string ResponseOutput{ | |
get {return _outputString.ToString();} | |
} | |
public override int StatusCode{get;set;} | |
public override string RedirectLocation{get;set;} | |
public override void Write(string s){ | |
_outputString.Append(s); | |
} | |
public override string ApplyAppPathModifier(string virtualPath){ | |
return virtualPath; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Fakes{ | |
using System.Collections; | |
using System.Collections.Specialized; | |
using System.Web; | |
using System.Web.SessionState; | |
public class FakeHttpSessionState:HttpSessionStateBase{ | |
private readonly SessionStateItemCollection _sessionItems; | |
public FakeHttpSessionState(SessionStateItemCollection sessionItems){ | |
_sessionItems=sessionItems; | |
} | |
public override int Count{ | |
get {return _sessionItems.Count;} | |
} | |
public override NameObjectCollectionBase.KeysCollection Keys{ | |
get {return _sessionItems.Keys;} | |
} | |
public override object this[string name]{ | |
get {return _sessionItems[name];} | |
set {_sessionItems[name]=value;} | |
} | |
public override object this[int index]{ | |
get {return _sessionItems[index];} | |
set {_sessionItems[index]=value;} | |
} | |
public bool Exists(string key){ | |
return _sessionItems[key]!=null; | |
} | |
public override void Add(string name,object value){ | |
_sessionItems[name]=value; | |
} | |
public override IEnumerator GetEnumerator(){ | |
return _sessionItems.GetEnumerator(); | |
} | |
public override void Remove(string name){ | |
_sessionItems.Remove(name); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Fakes{ | |
using System; | |
using System.Security.Principal; | |
public class FakeIdentity:IIdentity{ | |
private readonly string _name; | |
public FakeIdentity(string userName){ | |
_name=userName; | |
} | |
public string AuthenticationType{ | |
get {throw new NotImplementedException();} | |
} | |
public bool IsAuthenticated{ | |
get {return !String.IsNullOrEmpty(_name);} | |
} | |
public string Name{ | |
get {return _name;} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Fakes{ | |
using System.Linq; | |
using System.Security.Principal; | |
public class FakePrincipal:IPrincipal{ | |
private readonly IIdentity _identity; | |
private readonly string[] _roles; | |
public FakePrincipal(IIdentity identity,string[] roles){ | |
_identity=identity; | |
_roles=roles; | |
} | |
public IIdentity Identity{ | |
get {return _identity;} | |
} | |
public bool IsInRole(string role){ | |
return _roles!=null&&_roles.Contains(role); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Interreg.Integration.Web.Routing{ | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
using System.Web.Mvc; | |
using Xunit; | |
using ControllerBase=Interreg.Web.Controllers.Base; | |
public class MetaFacts{ | |
private readonly StringBuilder _sb=new StringBuilder(); | |
private Type _controller; | |
private IEnumerable<Type> _controllerClasses; | |
private Type _factClass; | |
private IEnumerable<Type> _factsClasses; | |
private bool pairFound; | |
[Fact] | |
public void AllRoutesAreTested(){ | |
_controllerClasses=GetControllerTypes(); | |
_factsClasses=GetRoutingFactTypes(); | |
_controllerClasses.ForEach(TestThatControllerIsTested); | |
if(_sb.Length>0) Assert.False(true,Environment.NewLine+_sb); | |
} | |
private void TestThatControllerIsTested(Type ct){ | |
_controller=ct; | |
pairFound=false; | |
_factsClasses.ForEach(TestFactClassAgainstController); | |
if(!pairFound) | |
_sb.AppendLine("No routing facts for '{0}'".With(_controller.Name)); | |
} | |
private void TestFactClassAgainstController(Type rt){ | |
_factClass=rt; | |
if(!PairFound()) return; | |
pairFound=true; | |
VerifyAllActionsAreTested(); | |
} | |
private void VerifyAllActionsAreTested(){ | |
var actions=GetActions(); | |
actions.ForEach(VerifyActionIsTested); | |
} | |
private void VerifyActionIsTested(string action){ | |
var facts=_factClass.GetMethods().Where(IsMarkedAsFact); | |
if(!facts.Any(f=>f.Name==action)) | |
_sb.AppendLine("No routing facts for '{0}#{1}' action" | |
.With(_controller.Name,action)); | |
} | |
#region boring | |
private static bool IsMarkedAsFact(MethodInfo mi){ | |
return mi.GetCustomAttributes(false).Any(a=>a.GetType().IsAssignableFrom(typeof(FactAttribute))); | |
} | |
private IEnumerable<string> GetActions(){ | |
return _controller.GetMethods() | |
.Where(IsAction) | |
.Where(IsNotBlacklistedAction) | |
.Select(x=>x.Name); | |
} | |
private IEnumerable<Type> GetRoutingFactTypes(){ | |
return GetType().Assembly.GetTypes().Where(IsRoutingFacts); | |
} | |
private static IEnumerable<Type> GetControllerTypes(){ | |
return typeof(ControllerBase).Assembly.GetTypes().Where(IsController); | |
} | |
private static bool IsAction(MethodInfo mi){ | |
return mi.ReturnType.IsAssignableFrom(typeof(ActionResult))|| | |
mi.ReturnType.IsAssignableFrom(typeof(PartialViewResult)); | |
} | |
private static bool IsNotBlacklistedAction(MethodInfo mi){ | |
return !mi.Name.IsOneOf("Do","View","get_ViewBag","PartialView"); | |
} | |
private static bool IsController(Type t){ | |
return t.BaseType==typeof(ControllerBase); | |
} | |
private static bool IsRoutingFacts(Type t){ | |
return t.BaseType==typeof(Base); | |
} | |
private bool PairFound(){ | |
return _controller.Name.Erase("Controller")==_factClass.Name.Erase("Facts"); | |
} | |
#endregion | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//shamelessly stolen from MvcContrib: http://bit.ly/dQfmT7 | |
namespace Interreg.Integration.Web.Extensions{ | |
using System; | |
using System.Collections.Specialized; | |
using System.Linq.Expressions; | |
using System.Web; | |
using System.Web.Mvc; | |
using System.Web.Routing; | |
using Fakes; | |
using Interreg.Domain; | |
using Interreg.Domain.Model; | |
using Mocks; | |
using SharpTestsEx; | |
using Xunit; | |
///<summary> | |
/// Used to simplify testing routes and restful testing routes | |
/// <example> | |
/// This tests that incoming PUT on resource is redirected to Update | |
/// "~/banner/1" | |
/// .WithMethod(HttpVerbs.Put) | |
/// .ShouldMapTo<BannerController>(action => action.Update(1)); | |
/// | |
/// This tests that incoming POST was a faux PUT using the _method=PUT form parameter | |
/// "~/banner/1" | |
/// .WithMethod(HttpVerbs.Post, HttpVerbs.Put) | |
/// .ShouldMapTo<BannerController>(action => action.Update(1)); | |
/// </example> | |
///</summary> | |
public static class RouteTestingExtensions{ | |
/// <summary> | |
/// A way to start the fluent interface and and which method to use | |
/// since you have a method constraint in the route. | |
/// </summary> | |
/// <param name = "url"></param> | |
/// <param name = "httpMethod"></param> | |
/// <returns></returns> | |
public static RouteData WithMethod(this string url,string httpMethod){ | |
return Route(url,httpMethod); | |
} | |
public static RouteData WithMethod(this string url,HttpVerbs verb){ | |
return WithMethod(url,verb.ToString("g")); | |
} | |
/// <summary> | |
/// Find the route for a URL and an Http Method | |
/// because you have a method contraint on the route | |
/// </summary> | |
/// <param name = "url"></param> | |
/// <param name = "httpMethod"></param> | |
/// <returns></returns> | |
public static RouteData Route(string url,string httpMethod){ | |
var context=FakeHttpContext(url,httpMethod); | |
return RouteTable.Routes.GetRouteData(context); | |
} | |
/// <summary> | |
/// Returns the corresponding route for the URL. Returns null if no route was found. | |
/// </summary> | |
/// <param name = "url">The app relative url to test.</param> | |
/// <returns>A matching <see cref = "RouteData" />, or null.</returns> | |
public static RouteData Route(this string url){ | |
var context=FakeHttpContext(url); | |
return RouteTable.Routes.GetRouteData(context); | |
} | |
/// <summary> | |
/// Returns the corresponding route for the URL. Returns null if no route was found. | |
/// </summary> | |
/// <param name = "url">The URL.</param> | |
/// <param name = "httpMethod">The HTTP method.</param> | |
/// <param name = "formMethod">The form method.</param> | |
/// <returns></returns> | |
public static RouteData Route(this string url,HttpVerbs httpMethod,HttpVerbs formMethod){ | |
var context=FakeHttpContext(url,httpMethod,formMethod); | |
var route=RouteTable.Routes.GetRouteData(context); | |
// cater for SimplyRestful methods and others | |
// adding values during the GetHttpHandler method | |
route.ReadValue(x=>x.RouteHandler).ReadValue(x=>x.GetHttpHandler(new RequestContext(context,route))); | |
return route; | |
} | |
/// <summary> | |
/// Returns the corresponding route for the URL. Returns null if no route was found. | |
/// </summary> | |
/// <param name = "url">The URL.</param> | |
/// <param name = "httpMethod">The HTTP method.</param> | |
/// <returns></returns> | |
public static RouteData Route(this string url,HttpVerbs httpMethod){ | |
var context=FakeHttpContext(url,httpMethod); | |
var route=RouteTable.Routes.GetRouteData(context); | |
// cater for SimplyRestful methods and others | |
// adding values during the GetHttpHandler method | |
route.ReadValue(x=>x.RouteHandler).ReadValue(x=>x.GetHttpHandler(new RequestContext(context,route))); | |
return route; | |
} | |
/// <summary> | |
/// Asserts that the route matches the expression specified based on the incoming HttpMethod and FormMethod for Simply Restful routing. Checks controller, action, and any method arguments | |
/// into the action as route values. | |
/// </summary> | |
/// <param name = "relativeUrl">The relative URL.</param> | |
/// <param name = "httpMethod">The HTTP method.</param> | |
/// <param name = "formMethod">The form method.</param> | |
/// <returns></returns> | |
public static RouteData WithMethod(this string relativeUrl,HttpVerbs httpMethod,HttpVerbs formMethod){ | |
return relativeUrl.Route(httpMethod,formMethod); | |
} | |
private static HttpContextBase FakeHttpContext(string url,HttpVerbs? httpMethod,HttpVerbs? formMethod){ | |
NameValueCollection form=null; | |
if(formMethod.HasValue) | |
form=new NameValueCollection {{"_method",formMethod.Value.ToString().ToUpper()}}; | |
if(!httpMethod.HasValue) | |
httpMethod=HttpVerbs.Get; | |
var mockFactory=new FirstAvailableMockFactory(); | |
var request=mockFactory.DynamicMock<HttpRequestBase>(); | |
request.ReturnFor(x=>x.AppRelativeCurrentExecutionFilePath,url); | |
request.ReturnFor(x=>x.PathInfo,string.Empty); | |
request.ReturnFor(x=>x.Form,form); | |
request.ReturnFor(x=>x.HttpMethod,httpMethod.Value.ToString().ToUpper()); | |
var context=new FakeHttpContext(url); | |
context.SetRequest(request.Object); | |
return context; | |
} | |
private static HttpContextBase FakeHttpContext(string url,string method){ | |
var httpMethod=(HttpVerbs)Enum.Parse(typeof(HttpVerbs),method); | |
return FakeHttpContext(url,httpMethod,null); | |
} | |
private static HttpContextBase FakeHttpContext(string url,HttpVerbs? httpMethod){ | |
return FakeHttpContext(url,httpMethod,null); | |
} | |
private static HttpContextBase FakeHttpContext(string url){ | |
return FakeHttpContext(url,null,null); | |
} | |
/// <summary> | |
/// Asserts that the route matches the expression specified. Checks controller, action, and any method arguments | |
/// into the action as route values. | |
/// </summary> | |
/// <typeparam name = "TController">The controller.</typeparam> | |
/// <param name = "routeData">The routeData to check</param> | |
/// <param name = "action">The action to call on TController.</param> | |
public static RouteData ShouldMapTo<TController>(this RouteData routeData, | |
Expression<Func<TController,ActionResult>> action) | |
where TController:Controller{ | |
if (routeData == null) | |
Assert.False(true,"The URL did not match any route"); | |
//routeData.Should().Not.Be.Null(); | |
//routeData.Should().Not.Be.Null("The URL did not match any route"); | |
//check controller | |
routeData.ShouldMapTo<TController>(); | |
//check action | |
var methodCall=(MethodCallExpression)action.Body; | |
var actualAction=routeData.Values.GetValue("action").ToString(); | |
var expectedAction=methodCall.Method.ActionName(); | |
//actualAction.AssertSameStringAs(expectedAction); | |
actualAction.Should().Be(expectedAction); | |
//check parameters | |
for(var i=0;i<methodCall.Arguments.Count;i++){ | |
var param=methodCall.Method.GetParameters()[i]; | |
var isReferenceType=!param.ParameterType.IsValueType; | |
var isNullable=isReferenceType|| | |
(param.ParameterType.UnderlyingSystemType.IsGenericType&& | |
param.ParameterType.UnderlyingSystemType.GetGenericTypeDefinition()==typeof(Nullable<>)); | |
var controllerParameterName=param.Name; | |
var routeDataContainsValueForParameterName=routeData.Values.ContainsKey(controllerParameterName); | |
var actual=routeData.Values.GetValue(controllerParameterName); | |
object expected=null; | |
var expressionToEvaluate=methodCall.Arguments[i]; | |
// If the parameter is nullable and the expression is a Convert UnaryExpression, | |
// we actually want to test against the value of the expression's operand. | |
if(expressionToEvaluate.NodeType==ExpressionType.Convert | |
&&expressionToEvaluate is UnaryExpression) | |
expressionToEvaluate=((UnaryExpression)expressionToEvaluate).Operand; | |
switch(expressionToEvaluate.NodeType){ | |
case ExpressionType.Constant: | |
expected=((ConstantExpression)expressionToEvaluate).Value; | |
break; | |
case ExpressionType.New: | |
case ExpressionType.MemberAccess: | |
expected=Expression.Lambda(expressionToEvaluate).Compile().DynamicInvoke(); | |
break; | |
} | |
if(isNullable&&(string)actual==String.Empty&&expected==null) | |
// The parameter is nullable so an expected value of '' is equivalent to null; | |
continue; | |
// HACK: this is only sufficient while System.Web.Mvc.UrlParameter has only a single value. | |
if(actual==UrlParameter.Optional|| | |
(actual!=null&&actual.ToString().Equals("System.Web.Mvc.UrlParameter"))) | |
actual=null; | |
if (expected is DateTime) | |
actual = Convert.ToDateTime(actual); | |
else if (expected is User) | |
expected=((User)expected).Id.ToString(); | |
else | |
expected = (expected == null ? expected : expected.ToString()); | |
var errorMsgFmt="Value for parameter '{0}' did not match: expected '{1}' but was '{2}'"; | |
if(routeDataContainsValueForParameterName) | |
errorMsgFmt+="."; | |
else | |
errorMsgFmt+= | |
"; no value found in the route context action parameter named '{0}' - does your matching route contain a token called '{0}'?"; | |
//actualValue.ShouldEqual(expectedValue, | |
// string.Format(errorMsgFmt,controllerParameterName,expectedValue,actualValue)); | |
//actualValue.Should().Be(expectedValue); | |
//if (expected!=null&&typeof(Entity).IsAssignableFm(expected.GetType())) | |
// expected=((Entity)expected).Id; | |
Assert.True(expected==null?actual==null:expected.Equals(actual), | |
string.Format(errorMsgFmt,controllerParameterName,expected,actual)); | |
} | |
return routeData; | |
} | |
/// <summary> | |
/// Converts the URL to matching RouteData and verifies that it will match a route with the values specified by the expression. | |
/// </summary> | |
/// <typeparam name = "TController">The type of controller</typeparam> | |
/// <param name = "relativeUrl">The ~/ based url</param> | |
/// <param name = "action">The expression that defines what action gets called (and with which parameters)</param> | |
/// <returns></returns> | |
public static RouteData ShouldMapTo<TController>(this string relativeUrl, | |
Expression<Func<TController,ActionResult>> action) | |
where TController:Controller{ | |
return relativeUrl.Route().ShouldMapTo(action); | |
} | |
/// <summary> | |
/// Verifies the <see cref = "RouteData">routeData</see> maps to the controller type specified. | |
/// </summary> | |
/// <typeparam name = "TController"></typeparam> | |
/// <param name = "routeData"></param> | |
/// <returns></returns> | |
public static RouteData ShouldMapTo<TController>(this RouteData routeData) where TController:Controller{ | |
//strip out the word 'Controller' from the type | |
var expected=typeof(TController).Name.Replace("Controller",""); | |
//get the key (case insensitive) | |
var actual=routeData.Values.GetValue("controller").ToString(); | |
//actual.AssertSameStringAs(expected); | |
//actual.Should().Be(expected); | |
Assert.True(actual==expected,"{0}!={1}. Route maps to wrong controller. Action: {2}" | |
.With(actual,expected,routeData.Values["action"])); | |
return routeData; | |
} | |
/// <summary> | |
/// Verifies the <see cref = "RouteData">routeData</see> will instruct the routing engine to ignore the route. | |
/// </summary> | |
/// <param name = "relativeUrl"></param> | |
/// <returns></returns> | |
public static RouteData ShouldBeIgnored(this string relativeUrl){ | |
var routeData=relativeUrl.Route(); | |
//routeData.RouteHandler.ShouldBe<StopRoutingHandler>("Expected StopRoutingHandler, but wasn't"); | |
routeData.RouteHandler.Should().Be.OfType<StopRoutingHandler>(); | |
return routeData; | |
} | |
/// <summary> | |
/// Gets a value from the <see cref = "RouteValueDictionary" /> by key. Does a | |
/// case-insensitive search on the keys. | |
/// </summary> | |
/// <param name = "routeValues"></param> | |
/// <param name = "key"></param> | |
/// <returns></returns> | |
public static object GetValue(this RouteValueDictionary routeValues,string key){ | |
foreach(var routeValueKey in routeValues.Keys) | |
if(string.Equals(routeValueKey,key,StringComparison.InvariantCultureIgnoreCase)){ | |
if(routeValues[routeValueKey]==null) | |
return null; | |
return routeValues[routeValueKey].ToString(); | |
} | |
return null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment