-
-
Save zinto/75a9833cc8e2e72e0ca6 to your computer and use it in GitHub Desktop.
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
using System; | |
using System.Collections.Specialized; | |
using System.IO; | |
using System.Text; | |
using System.Text.RegularExpressions; | |
using System.Web; | |
using System.Web.Configuration; | |
using System.Web.Hosting; | |
using System.Web.SessionState; | |
namespace Onboard.Tests.ZeroFriction.HttpMocking | |
{ | |
public enum HttpVerb | |
{ | |
GET, | |
HEAD, | |
POST, | |
PUT, | |
DELETE, | |
} | |
/// <summary> | |
/// Useful class for simulating the HttpContext. This does not actually | |
/// make an HttpRequest, it merely simulates the state that your code | |
/// would be in "as if" handling a request. Thus the HttpContext.Current | |
/// property is populated. | |
/// http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx | |
/// </summary> | |
public class HttpSimulator : IDisposable | |
{ | |
private const string DefaultPhysicalAppPath = @"c:\InetPub\wwwRoot\"; | |
private readonly NameValueCollection headers = new NameValueCollection(); | |
private readonly NameValueCollection formVars = new NameValueCollection(); | |
private StringBuilder builder; | |
private Uri referrer; | |
private string page; | |
public HttpSimulator() | |
: this("/", DefaultPhysicalAppPath) | |
{ | |
} | |
public HttpSimulator(string applicationPath) | |
: this(applicationPath, DefaultPhysicalAppPath) | |
{ | |
} | |
public HttpSimulator(string applicationPath, string physicalApplicationPath) | |
{ | |
this.ApplicationPath = applicationPath; | |
this.PhysicalApplicationPath = physicalApplicationPath; | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a GET request. | |
/// </summary> | |
/// <remarks> | |
/// Simulates a request to http://localhost/ | |
/// </remarks> | |
public HttpSimulator SimulateRequest() | |
{ | |
return SimulateRequest(new Uri("http://localhost/")); | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a GET request. | |
/// </summary> | |
/// <param name="url"></param> | |
public HttpSimulator SimulateRequest(Uri url) | |
{ | |
return SimulateRequest(url, HttpVerb.GET); | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a request. | |
/// </summary> | |
/// <param name="url"></param> | |
/// <param name="httpVerb"></param> | |
public HttpSimulator SimulateRequest(Uri url, HttpVerb httpVerb) | |
{ | |
return SimulateRequest(url, httpVerb, null, null); | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a POST request. | |
/// </summary> | |
/// <param name="url"></param> | |
/// <param name="formVariables"></param> | |
public HttpSimulator SimulateRequest(Uri url, NameValueCollection formVariables) | |
{ | |
return SimulateRequest(url, HttpVerb.POST, formVariables, null); | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a POST request. | |
/// </summary> | |
/// <param name="url"></param> | |
/// <param name="formVariables"></param> | |
/// <param name="headers"></param> | |
public HttpSimulator SimulateRequest(Uri url, NameValueCollection formVariables, NameValueCollection headers) | |
{ | |
return SimulateRequest(url, HttpVerb.POST, formVariables, headers); | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a request. | |
/// </summary> | |
/// <param name="url"></param> | |
/// <param name="httpVerb"></param> | |
/// <param name="headers"></param> | |
public HttpSimulator SimulateRequest(Uri url, HttpVerb httpVerb, NameValueCollection headers) | |
{ | |
return SimulateRequest(url, httpVerb, null, headers); | |
} | |
/// <summary> | |
/// Sets up the HttpContext objects to simulate a request. | |
/// </summary> | |
/// <param name="url"></param> | |
/// <param name="httpVerb"></param> | |
/// <param name="formVariables"></param> | |
/// <param name="headers"></param> | |
protected virtual HttpSimulator SimulateRequest(Uri url, HttpVerb httpVerb, NameValueCollection formVariables, NameValueCollection headers) | |
{ | |
HttpContext.Current = null; | |
ParseRequestUrl(url); | |
if (this.responseWriter == null) | |
{ | |
this.builder = new StringBuilder(); | |
this.responseWriter = new StringWriter(builder); | |
} | |
SetHttpRuntimeInternals(); | |
var query = ExtractQueryStringPart(url); | |
if (formVariables != null) | |
{ | |
formVars.Add(formVariables); | |
} | |
if (formVars.Count > 0) | |
{ | |
httpVerb = HttpVerb.POST; //Need to enforce this. | |
} | |
if (headers != null) | |
{ | |
this.headers.Add(headers); | |
} | |
this.workerRequest = new SimulatedHttpRequest(ApplicationPath, PhysicalApplicationPath, PhysicalPath, Page, query, this.responseWriter, host, port, httpVerb.ToString()); | |
this.workerRequest.Form.Add(formVars); | |
this.workerRequest.Headers.Add(this.headers); | |
if (referrer != null) | |
{ | |
this.workerRequest.SetReferrer(referrer); | |
} | |
InitializeSession(); | |
InitializeApplication(); | |
#region Console Debug INfo | |
Console.WriteLine("host: " + host); | |
Console.WriteLine("virtualDir: " + applicationPath); | |
Console.WriteLine("page: " + localPath); | |
Console.WriteLine("pathPartAfterApplicationPart: " + page); | |
Console.WriteLine("appPhysicalDir: " + physicalApplicationPath); | |
Console.WriteLine("Request.Url.LocalPath: " + HttpContext.Current.Request.Url.LocalPath); | |
Console.WriteLine("Request.Url.Host: " + HttpContext.Current.Request.Url.Host); | |
Console.WriteLine("Request.FilePath: " + HttpContext.Current.Request.FilePath); | |
Console.WriteLine("Request.Path: " + HttpContext.Current.Request.Path); | |
Console.WriteLine("Request.RawUrl: " + HttpContext.Current.Request.RawUrl); | |
Console.WriteLine("Request.Url: " + HttpContext.Current.Request.Url); | |
Console.WriteLine("Request.Url.Port: " + HttpContext.Current.Request.Url.Port); | |
Console.WriteLine("Request.ApplicationPath: " + HttpContext.Current.Request.ApplicationPath); | |
Console.WriteLine("Request.PhysicalPath: " + HttpContext.Current.Request.PhysicalPath); | |
Console.WriteLine("HttpRuntime.AppDomainAppPath: " + HttpRuntime.AppDomainAppPath); | |
Console.WriteLine("HttpRuntime.AppDomainAppVirtualPath: " + HttpRuntime.AppDomainAppVirtualPath); | |
Console.WriteLine("HostingEnvironment.ApplicationPhysicalPath: " + HostingEnvironment.ApplicationPhysicalPath); | |
Console.WriteLine("HostingEnvironment.ApplicationVirtualPath: " + HostingEnvironment.ApplicationVirtualPath); | |
#endregion | |
return this; | |
} | |
private static void InitializeApplication() | |
{ | |
Type appFactoryType = Type.GetType("System.Web.HttpApplicationFactory, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); | |
object appFactory = ReflectionHelper.GetStaticFieldValue<object>("_theApplicationFactory", appFactoryType); | |
ReflectionHelper.SetPrivateInstanceFieldValue("_state", appFactory, HttpContext.Current.Application); | |
} | |
private void InitializeSession() | |
{ | |
HttpContext.Current = new HttpContext(workerRequest); | |
HttpContext.Current.Items.Clear(); | |
var session = (HttpSessionState)ReflectionHelper.Instantiate(typeof(HttpSessionState), new Type[] { typeof(IHttpSessionState) }, new FakeHttpSessionState()); | |
HttpContext.Current.Items.Add("AspSession", session); | |
} | |
public class FakeHttpSessionState : NameObjectCollectionBase, IHttpSessionState | |
{ | |
private readonly bool isNewSession = true; | |
private readonly string sessionID = Guid.NewGuid().ToString(); | |
private readonly HttpStaticObjectsCollection staticObjects = new HttpStaticObjectsCollection(); | |
private readonly object syncRoot = new Object(); | |
private int timeout = 30; //minutes | |
private int lcid; | |
private int codePage; | |
/// <summary> | |
/// Ends the current session. | |
/// </summary> | |
/// | |
public void Abandon() | |
{ | |
BaseClear(); | |
} | |
/// <summary> | |
/// Adds a new item to the session-state collection. | |
/// </summary> | |
/// <param name="name">The name of the item to add to the session-state collection. </param> | |
/// <param name="value">The value of the item to add to the session-state collection. </param> | |
public void Add(string name, object value) | |
{ | |
BaseAdd(name, value); | |
} | |
/// <summary> | |
/// Deletes an item from the session-state item collection. | |
/// </summary> | |
/// <param name="name">The name of the item to delete from the session-state item collection. </param> | |
public void Remove(string name) | |
{ | |
BaseRemove(name); | |
} | |
/// <summary> | |
/// Deletes an item at a specified index from the session-state item collection. | |
/// </summary> | |
/// <param name="index">The index of the item to remove from the session-state collection. </param> | |
public void RemoveAt(int index) | |
{ | |
BaseRemoveAt(index); | |
} | |
/// <summary> | |
/// Clears all values from the session-state item collection. | |
/// </summary> | |
public void Clear() | |
{ | |
BaseClear(); | |
} | |
/// <summary> | |
/// Clears all values from the session-state item collection. | |
/// </summary> | |
public void RemoveAll() | |
{ | |
BaseClear(); | |
} | |
/// <summary> | |
/// Copies the collection of session-state item values to a one-dimensional array, starting at the specified index in the array. | |
/// </summary> | |
/// <param name="array">The <see cref="T:System.Array"></see> that receives the session values. </param> | |
/// <param name="index">The index in array where copying starts. </param> | |
public void CopyTo(Array array, int index) | |
{ | |
throw new NotImplementedException(); | |
} | |
/// <summary> | |
/// Gets the unique session identifier for the session. | |
/// </summary> | |
/// <returns> The session ID. </returns> | |
public string SessionID | |
{ | |
get { return sessionID; } | |
} | |
/// <summary> | |
/// Gets and sets the time-out period (in minutes) allowed between requests before the session-state provider terminates the session. | |
/// </summary> | |
/// <returns> The time-out period, in minutes. </returns> | |
public int Timeout | |
{ | |
get { return timeout; } | |
set { timeout = value; } | |
} | |
/// <summary> | |
/// Gets a value indicating whether the session was created with the current request. | |
/// </summary> | |
/// <returns> true if the session was created with the current request; otherwise, false. </returns> | |
/// | |
public bool IsNewSession | |
{ | |
get { return isNewSession; } | |
} | |
/// <summary> | |
/// Gets the current session-state mode. | |
/// </summary> | |
/// <returns> One of the <see cref="T:System.Web.SessionState.SessionStateMode"></see> values. </returns> | |
public SessionStateMode Mode | |
{ | |
get { return SessionStateMode.InProc; } | |
} | |
/// <summary> | |
/// Gets a value indicating whether the session ID is embedded in the URL or stored in an HTTP cookie. | |
/// </summary> | |
/// | |
/// <returns> | |
/// true if the session is embedded in the URL; otherwise, false. | |
/// </returns> | |
/// | |
public bool IsCookieless | |
{ | |
get { return false; } | |
} | |
/// <summary> | |
/// Gets a value that indicates whether the application is configured for cookieless sessions. | |
/// </summary> | |
/// | |
/// <returns> | |
/// One of the <see cref="T:System.Web.HttpCookieMode"></see> values that indicate whether the application is configured for cookieless sessions. The default is <see cref="F:System.Web.HttpCookieMode.UseCookies"></see>. | |
/// </returns> | |
/// | |
public HttpCookieMode CookieMode | |
{ | |
get { return HttpCookieMode.UseCookies; } | |
} | |
/// <summary> | |
/// Gets or sets the locale identifier (LCID) of the current session. | |
/// </summary> | |
/// | |
/// <returns> | |
/// A <see cref="T:System.Globalization.CultureInfo"></see> instance that specifies the culture of the current session. | |
/// </returns> | |
/// | |
public int LCID | |
{ | |
get { return lcid; } | |
set { lcid = value; } | |
} | |
/// <summary> | |
/// Gets or sets the code-page identifier for the current session. | |
/// </summary> | |
/// | |
/// <returns> | |
/// The code-page identifier for the current session. | |
/// </returns> | |
/// | |
public int CodePage | |
{ | |
get { return codePage; } | |
set { codePage = value; } | |
} | |
/// <summary> | |
/// Gets a collection of objects declared by <object Runat="Server" Scope="Session"/> tags within the ASP.NET application file Global.asax. | |
/// </summary> | |
/// | |
/// <returns> | |
/// An <see cref="T:System.Web.HttpStaticObjectsCollection"></see> containing objects declared in the Global.asax file. | |
/// </returns> | |
/// | |
public HttpStaticObjectsCollection StaticObjects | |
{ | |
get { return staticObjects; } | |
} | |
/// <summary> | |
/// Gets or sets a session-state item value by name. | |
/// </summary> | |
/// | |
/// <returns> | |
/// The session-state item value specified in the name parameter. | |
/// </returns> | |
/// | |
/// <param name="name">The key name of the session-state item value. </param> | |
public object this[string name] | |
{ | |
get { return BaseGet(name); } | |
set { BaseSet(name, value); } | |
} | |
/// <summary> | |
/// Gets or sets a session-state item value by numerical index. | |
/// </summary> | |
/// | |
/// <returns> | |
/// The session-state item value specified in the index parameter. | |
/// </returns> | |
/// | |
/// <param name="index">The numerical index of the session-state item value. </param> | |
public object this[int index] | |
{ | |
get { return BaseGet(index); } | |
set { BaseSet(index, value); } | |
} | |
/// <summary> | |
/// Gets an object that can be used to synchronize access to the collection of session-state values. | |
/// </summary> | |
/// | |
/// <returns> | |
/// An object that can be used to synchronize access to the collection. | |
/// </returns> | |
/// | |
public object SyncRoot | |
{ | |
get { return syncRoot; } | |
} | |
/// <summary> | |
/// Gets a value indicating whether access to the collection of session-state values is synchronized (thread safe). | |
/// </summary> | |
/// <returns> | |
/// true if access to the collection is synchronized (thread safe); otherwise, false. | |
/// </returns> | |
/// | |
public bool IsSynchronized | |
{ | |
get { return true; } | |
} | |
/// <summary> | |
/// Gets a value indicating whether the session is read-only. | |
/// </summary> | |
/// | |
/// <returns> | |
/// true if the session is read-only; otherwise, false. | |
/// </returns> | |
/// | |
bool IHttpSessionState.IsReadOnly | |
{ | |
get | |
{ | |
return true; | |
} | |
} | |
} | |
/// <summary> | |
/// Sets the referrer for the request. Uses a fluent interface. | |
/// </summary> | |
/// <param name="referer"></param> | |
/// <returns></returns> | |
public HttpSimulator SetReferer(Uri referer) | |
{ | |
if (this.workerRequest != null) | |
{ | |
this.workerRequest.SetReferrer(referer); | |
} | |
this.referrer = referer; | |
return this; | |
} | |
/// <summary> | |
/// Sets a form variable. | |
/// </summary> | |
/// <param name="name"></param> | |
/// <param name="value"></param> | |
/// <returns></returns> | |
public HttpSimulator SetFormVariable(string name, string value) | |
{ | |
if (this.workerRequest != null) | |
{ | |
throw new InvalidOperationException("Cannot set form variables after calling Simulate()."); | |
} | |
formVars.Add(name, value); | |
return this; | |
} | |
/// <summary> | |
/// Sets a header value. | |
/// </summary> | |
/// <param name="name"></param> | |
/// <param name="value"></param> | |
/// <returns></returns> | |
public HttpSimulator SetHeader(string name, string value) | |
{ | |
if (this.workerRequest != null) | |
{ | |
throw new InvalidOperationException("Cannot set headers after calling Simulate()."); | |
} | |
headers.Add(name, value); | |
return this; | |
} | |
private void ParseRequestUrl(Uri url) | |
{ | |
if (url == null) | |
{ | |
return; | |
} | |
this.host = url.Host; | |
this.port = url.Port; | |
this.localPath = url.LocalPath; | |
this.page = StripPrecedingSlashes(RightAfter(url.LocalPath, ApplicationPath)); | |
this.physicalPath = Path.Combine(this.physicalApplicationPath, this.page.Replace("/", @"\")); | |
} | |
static string RightAfter(string original, string search) | |
{ | |
if (search.Length > original.Length || search.Length == 0) | |
{ | |
return original; | |
} | |
var searchIndex = original.IndexOf(search, 0, StringComparison.InvariantCultureIgnoreCase); | |
if (searchIndex < 0) | |
{ | |
return original; | |
} | |
return original.Substring(original.IndexOf(search) + search.Length); | |
} | |
public string Host | |
{ | |
get { return this.host; } | |
} | |
private string host; | |
public string LocalPath | |
{ | |
get { return this.localPath; } | |
} | |
private string localPath; | |
public int Port | |
{ | |
get { return this.port; } | |
} | |
private int port; | |
/// <summary> | |
/// Portion of the URL after the application. | |
/// </summary> | |
public string Page | |
{ | |
get { return this.page; } | |
} | |
/// <summary> | |
/// The same thing as the IIS Virtual directory. It's | |
/// what gets returned by Request.ApplicationPath. | |
/// </summary> | |
public string ApplicationPath | |
{ | |
get | |
{ | |
return this.applicationPath; | |
} | |
set | |
{ | |
this.applicationPath = value ?? "/"; | |
this.applicationPath = NormalizeSlashes(this.applicationPath); | |
} | |
} | |
private string applicationPath = "/"; | |
/// <summary> | |
/// Physical path to the application (used for simulation purposes). | |
/// </summary> | |
public string PhysicalApplicationPath | |
{ | |
get | |
{ | |
return this.physicalApplicationPath; | |
} | |
set | |
{ | |
this.physicalApplicationPath = value ?? DefaultPhysicalAppPath; | |
//strip trailing backslashes. | |
this.physicalApplicationPath = StripTrailingBackSlashes(this.physicalApplicationPath) + @"\"; | |
} | |
} | |
private string physicalApplicationPath = DefaultPhysicalAppPath; | |
/// <summary> | |
/// Physical path to the requested file (used for simulation purposes). | |
/// </summary> | |
public string PhysicalPath | |
{ | |
get { return this.physicalPath; } | |
} | |
private string physicalPath = DefaultPhysicalAppPath; | |
public TextWriter ResponseWriter | |
{ | |
get { return this.responseWriter; } | |
set { this.responseWriter = value; } | |
} | |
/// <summary> | |
/// Returns the text from the response to the simulated request. | |
/// </summary> | |
public string ResponseText | |
{ | |
get | |
{ | |
return (builder ?? new StringBuilder()).ToString(); | |
} | |
} | |
private TextWriter responseWriter; | |
public SimulatedHttpRequest WorkerRequest | |
{ | |
get { return this.workerRequest; } | |
} | |
private SimulatedHttpRequest workerRequest; | |
private static string ExtractQueryStringPart(Uri url) | |
{ | |
string query = url.Query ?? string.Empty; | |
if (query.StartsWith("?")) | |
{ | |
return query.Substring(1); | |
} | |
return query; | |
} | |
void SetHttpRuntimeInternals() | |
{ | |
//We cheat by using reflection. | |
// get singleton property value | |
var runtime = ReflectionHelper.GetStaticFieldValue<HttpRuntime>("_theRuntime", typeof(HttpRuntime)); | |
// set app path property value | |
ReflectionHelper.SetPrivateInstanceFieldValue("_appDomainAppPath", runtime, PhysicalApplicationPath); | |
// set app virtual path property value | |
const string VpathTypeName = "System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; | |
var virtualPath = ReflectionHelper.Instantiate(VpathTypeName, new Type[] { typeof(string) }, new object[] { ApplicationPath }); | |
ReflectionHelper.SetPrivateInstanceFieldValue("_appDomainAppVPath", runtime, virtualPath); | |
// set codegen dir property value | |
ReflectionHelper.SetPrivateInstanceFieldValue("_codegenDir", runtime, PhysicalApplicationPath); | |
HostingEnvironment environment = GetHostingEnvironment(); | |
ReflectionHelper.SetPrivateInstanceFieldValue("_appPhysicalPath", environment, PhysicalApplicationPath); | |
ReflectionHelper.SetPrivateInstanceFieldValue("_appVirtualPath", environment, virtualPath); | |
ReflectionHelper.SetPrivateInstanceFieldValue("_configMapPath", environment, new ConfigMapPath(this)); | |
} | |
protected static HostingEnvironment GetHostingEnvironment() | |
{ | |
HostingEnvironment environment; | |
try | |
{ | |
environment = new HostingEnvironment(); | |
} | |
catch (InvalidOperationException) | |
{ | |
//Shoot, we need to grab it via reflection. | |
environment = ReflectionHelper.GetStaticFieldValue<HostingEnvironment>("_theHostingEnvironment", typeof(HostingEnvironment)); | |
} | |
return environment; | |
} | |
#region --- Text Manipulation Methods for slashes --- | |
protected static string NormalizeSlashes(string s) | |
{ | |
if (String.IsNullOrEmpty(s) || s == "/") | |
{ | |
return "/"; | |
} | |
s = s.Replace(@"\", "/"); | |
//Reduce multiple slashes in row to single. | |
var normalized = Regex.Replace(s, "(/)/+", "$1"); | |
//Strip left. | |
normalized = StripPrecedingSlashes(normalized); | |
//Strip right. | |
normalized = StripTrailingSlashes(normalized); | |
return "/" + normalized; | |
} | |
protected static string StripPrecedingSlashes(string s) | |
{ | |
return Regex.Replace(s, "^/*(.*)", "$1"); | |
} | |
protected static string StripTrailingSlashes(string s) | |
{ | |
return Regex.Replace(s, "(.*)/*$", "$1", RegexOptions.RightToLeft); | |
} | |
protected static string StripTrailingBackSlashes(string s) | |
{ | |
if (String.IsNullOrEmpty(s)) | |
{ | |
return string.Empty; | |
} | |
return Regex.Replace(s, @"(.*)\\*$", "$1", RegexOptions.RightToLeft); | |
} | |
#endregion | |
internal class ConfigMapPath : IConfigMapPath | |
{ | |
private readonly HttpSimulator requestSimulation; | |
public ConfigMapPath(HttpSimulator simulation) | |
{ | |
requestSimulation = simulation; | |
} | |
public string GetMachineConfigFilename() | |
{ | |
throw new NotImplementedException(); | |
} | |
public string GetRootWebConfigFilename() | |
{ | |
throw new NotImplementedException(); | |
} | |
public void GetPathConfigFilename(string siteID, string path, out string directory, out string baseName) | |
{ | |
throw new NotImplementedException(); | |
} | |
public void GetDefaultSiteNameAndID(out string siteName, out string siteID) | |
{ | |
throw new NotImplementedException(); | |
} | |
public void ResolveSiteArgument(string siteArgument, out string siteName, out string siteID) | |
{ | |
throw new NotImplementedException(); | |
} | |
public string MapPath(string siteID, string path) | |
{ | |
string page = StripPrecedingSlashes(RightAfter(path, requestSimulation.ApplicationPath)); | |
return Path.Combine(requestSimulation.PhysicalApplicationPath, page.Replace("/", @"\")); | |
} | |
public string GetAppPathForPath(string siteID, string path) | |
{ | |
return requestSimulation.ApplicationPath; | |
} | |
} | |
/// <summary> | |
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. | |
/// </summary> | |
/// <filterpriority>2</filterpriority> | |
public void Dispose() | |
{ | |
if (HttpContext.Current != null) | |
{ | |
HttpContext.Current = 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
using System; | |
using System.Collections.Specialized; | |
using System.Reflection; | |
using System.Web; | |
using System.Web.Hosting; | |
using NUnit.Framework; | |
namespace Onboard.Tests.ZeroFriction.HttpMocking | |
{ | |
[TestFixture, Category("Example")] | |
public class HttpSimulatorTests | |
{ | |
internal class TestHttpHandler : IHttpHandler | |
{ | |
public void ProcessRequest(HttpContext context) | |
{ | |
var physicalPath = context.Request.MapPath("/MyHandler.ashx"); | |
var username = context.Request.Form["username"]; | |
var id = context.Request.QueryString["id"]; | |
var referer = context.Request.UrlReferrer.ToString(); | |
//Imagine, if you will, a bunch of complex interesting | |
//and fascinating logic here. | |
context.Response.Write(physicalPath + ":" + username + ":" + id + ":" + referer); | |
} | |
public bool IsReusable | |
{ | |
get { return true; } | |
} | |
} | |
[Test] | |
public void CanGetSetSession() | |
{ | |
using (new HttpSimulator("/", @"c:\inetpub\").SimulateRequest()) | |
{ | |
HttpContext.Current.Session["Test"] = "Success"; | |
Assert.AreEqual("Success", HttpContext.Current.Session["Test"], "Was not able to retrieve session variable."); | |
} | |
} | |
[Test] | |
public void CanGetSetApplicationVariables() | |
{ | |
using (new HttpSimulator("/", @"c:\inetpub\").SimulateRequest()) | |
{ | |
HttpContext.Current.Application["Test"] = "Success"; | |
Assert.AreEqual("Success", HttpContext.Current.Application["Test"], "Was not able to retrieve application variable."); | |
} | |
} | |
[Test] | |
public void TestHttpHandlerWritesCorrectResponse() | |
{ | |
using (HttpSimulator simulator = new HttpSimulator("/", @"c:\inetpub\")) | |
{ | |
simulator.SetFormVariable("username", "phil") | |
.SetReferer(new Uri("http://example.com/1/")) | |
.SimulateRequest(new Uri("http://localhost/MyHandler.ashx?id=1234")); | |
TestHttpHandler handler = new TestHttpHandler(); | |
handler.ProcessRequest(HttpContext.Current); | |
HttpContext.Current.Response.Flush(); | |
string expected = @"c:\inetpub\MyHandler.ashx:phil:1234:http://example.com/1/"; | |
Assert.AreEqual(expected, simulator.ResponseText, "The Expected Response is all wrong."); | |
} //HttpContext.Current is set to null again. | |
} | |
[Test] | |
public void CanDispose() | |
{ | |
using (HttpSimulator simulator = new HttpSimulator()) | |
{ | |
simulator.SimulateRequest(); | |
Assert.IsNotNull(HttpContext.Current); | |
} | |
Assert.IsNull(HttpContext.Current); | |
} | |
[TestCase("http://localhost/Test/Default.aspx", "/Test", "/Test")] | |
[TestCase("http://localhost/Test/Default.aspx", "/Test/", "/Test")] | |
[TestCase("http://localhost/Test/Default.aspx", "//Test//", "/Test")] | |
[TestCase("http://localhost/Test/Subtest/Default.aspx", "/Test", "/Test")] | |
[TestCase("http://localhost/Test/Subtest/Default.aspx", "/Test/", "/Test")] | |
[TestCase("http://localhost/Test/Subtest/Default.aspx", "//Test//", "/Test")] | |
[TestCase("http://localhost/Test/Default.aspx", "", "/")] | |
[TestCase("http://localhost/Test/Default.aspx", "/", "/")] | |
[TestCase("http://localhost/Test/Default.aspx", null, "/")] | |
public void CanSetApplicationPathCorrectly(string url, string appPath, string expectedAppPath) | |
{ | |
HttpSimulator simulator = new HttpSimulator(appPath, @"c:\inetpub\wwwroot\site1\test"); | |
Assert.AreEqual(expectedAppPath, simulator.ApplicationPath); | |
simulator.SimulateRequest(new Uri(url)); | |
Assert.AreEqual(expectedAppPath, HttpContext.Current.Request.ApplicationPath); | |
Assert.AreEqual(expectedAppPath, HttpRuntime.AppDomainAppVirtualPath); | |
Assert.AreEqual(expectedAppPath, HostingEnvironment.ApplicationVirtualPath); | |
} | |
[TestCase("http://localhost/Test/default.aspx", "/Test", @"c:\projects\test", @"c:\projects\test\", @"c:\projects\test\default.aspx")] | |
[TestCase("http://localhost/Test/Subtest/default.aspx", "/Test", @"c:\projects\test", @"c:\projects\test\", @"c:\projects\test\Subtest\default.aspx")] | |
[TestCase("http://localhost/test/default.aspx", "/", @"c:\inetpub\wwwroot\", @"c:\inetpub\wwwroot\", @"c:\inetpub\wwwroot\test\default.aspx")] | |
[TestCase("http://localhost/test/default.aspx", "/", @"c:\inetpub\wwwroot", @"c:\inetpub\wwwroot\", @"c:\inetpub\wwwroot\test\default.aspx")] | |
public void CanSetAppPhysicalPathCorrectly(string url, string appPath, string appPhysicalPath, string expectedPhysicalAppPath, string expectedPhysicalPath) | |
{ | |
HttpSimulator simulator = new HttpSimulator(appPath, appPhysicalPath); | |
Assert.AreEqual(expectedPhysicalAppPath, simulator.PhysicalApplicationPath); | |
simulator.SimulateRequest(new Uri(url), HttpVerb.GET); | |
Assert.AreEqual(expectedPhysicalPath, simulator.PhysicalPath); | |
Assert.AreEqual(expectedPhysicalAppPath, HttpRuntime.AppDomainAppPath); | |
Assert.AreEqual(expectedPhysicalAppPath, HostingEnvironment.ApplicationPhysicalPath); | |
Assert.AreEqual(expectedPhysicalPath, HttpContext.Current.Request.PhysicalPath); | |
} | |
[Test] | |
public void CanGetQueryString() | |
{ | |
var simulator = new HttpSimulator(); | |
simulator.SimulateRequest(new Uri("http://localhost/Test.aspx?param1=value1¶m2=value2¶m3=value3")); | |
for (var i = 1; i <= 3; i++) | |
{ | |
Assert.AreEqual("value" + i, HttpContext.Current.Request.QueryString["param" + i], "Could not find query string field 'param{0}'", i); | |
} | |
simulator.SimulateRequest(new Uri("http://localhost/Test.aspx?param1=new-value1¶m2=new-value2¶m3=new-value3¶m4=new-value4")); | |
for (var i = 1; i <= 4; i++) | |
{ | |
Assert.AreEqual("new-value" + i, HttpContext.Current.Request.QueryString["param" + i], "Could not find query string field 'param{0}'", i); | |
} | |
simulator.SimulateRequest(new Uri("http://localhost/Test.aspx?")); | |
Assert.AreEqual(string.Empty, HttpContext.Current.Request.QueryString.ToString()); | |
Assert.AreEqual(0, HttpContext.Current.Request.QueryString.Count); | |
simulator.SimulateRequest(new Uri("http://localhost/Test.aspx")); | |
Assert.AreEqual(string.Empty, HttpContext.Current.Request.QueryString.ToString()); | |
Assert.AreEqual(0, HttpContext.Current.Request.QueryString.Count); | |
simulator.SimulateRequest(new Uri("http://localhost/Test.aspx?param-name")); | |
Assert.AreEqual("param-name", HttpContext.Current.Request.QueryString.ToString()); | |
Assert.AreEqual(1, HttpContext.Current.Request.QueryString.Count); | |
Assert.IsNull(HttpContext.Current.Request.QueryString["param-name"]); | |
} | |
[Test] | |
public void CanSimulateFormPost() | |
{ | |
using (var simulator = new HttpSimulator()) | |
{ | |
var form = new NameValueCollection(); | |
form.Add("Test1", "Value1"); | |
form.Add("Test2", "Value2"); | |
simulator.SimulateRequest(new Uri("http://localhost/Test.aspx"), form); | |
Assert.AreEqual("Value1", HttpContext.Current.Request.Form["Test1"]); | |
Assert.AreEqual("Value2", HttpContext.Current.Request.Form["Test2"]); | |
} | |
using (var simulator = new HttpSimulator()) | |
{ | |
simulator.SetFormVariable("Test1", "Value1") | |
.SetFormVariable("Test2", "Value2") | |
.SimulateRequest(new Uri("http://localhost/Test.aspx")); | |
Assert.AreEqual("Value1", HttpContext.Current.Request.Form["Test1"]); | |
Assert.AreEqual("Value2", HttpContext.Current.Request.Form["Test2"]); | |
} | |
} | |
[Test] | |
public void CanGetResponse() | |
{ | |
HttpSimulator simulator = new HttpSimulator(); | |
simulator.SimulateRequest(); | |
HttpContext.Current.Response.Write("Hello World!"); | |
HttpContext.Current.Response.Flush(); | |
Assert.AreEqual("Hello World!", simulator.ResponseText); | |
} | |
[Test] | |
public void CanGetReferer() | |
{ | |
HttpSimulator simulator = new HttpSimulator(); | |
simulator.SetReferer(new Uri("http://example.com/Blah.aspx")).SimulateRequest(); | |
Assert.AreEqual(new Uri("http://example.com/Blah.aspx"), HttpContext.Current.Request.UrlReferrer); | |
simulator = new HttpSimulator(); | |
simulator.SimulateRequest().SetReferer(new Uri("http://x.example.com/Blah.aspx")); | |
Assert.AreEqual(new Uri("http://x.example.com/Blah.aspx"), HttpContext.Current.Request.UrlReferrer); | |
} | |
[TestCase("http://localhost:60653/Test.aspx", null, null, "localhost", 60653, "/", "/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/Test.aspx?test=true", null, null, "localhost", 60653, "/", "/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/Test.aspx", "/", @"c:\InetPub\wwwRoot\", "localhost", 60653, "/", "/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/Test/Test.aspx", "/", @"c:\InetPub\wwwRoot\", "localhost", 60653, "/", "/Test/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/AppPath/Test.aspx", "/AppPath", @"c:\InetPub\wwwRoot\AppPath\", "localhost", 60653, "/AppPath", "/AppPath/Test.aspx", @"c:\InetPub\wwwRoot\AppPath\")] | |
[TestCase("http://localhost:60653/AppPath/Test.aspx", "/AppPath/", @"c:\InetPub\wwwRoot\AppPath\", "localhost", 60653, "/AppPath", "/AppPath/Test.aspx", @"c:\InetPub\wwwRoot\AppPath\")] | |
public void CanParseRequestUrl(string url, string appPath, string physicalPath, string expectedHost, int expectedPort, string expectedAppPath, string expectedPage, string expectedAppDomainAppPath) | |
{ | |
HttpSimulator simulator = new HttpSimulator(appPath, physicalPath); | |
Assert.AreEqual(expectedAppPath, simulator.ApplicationPath); | |
Assert.AreEqual(expectedAppDomainAppPath, simulator.PhysicalApplicationPath); | |
} | |
[TestCase("http://localhost/AppPath/default.aspx", "/AppPath", "/AppPath/default.aspx")] | |
[TestCase("http://localhost/AppPath/default.aspx", "/", "/AppPath/default.aspx")] | |
public void CanGetLocalPathCorrectly(string url, string appPath, string expectedLocalPath) | |
{ | |
HttpSimulator simulator = new HttpSimulator(appPath, @"c:\inetpub\wwwroot\AppPath\"); | |
simulator.SimulateRequest(new Uri(url)); | |
Assert.AreEqual(expectedLocalPath, HttpContext.Current.Request.Path); | |
Assert.AreEqual(expectedLocalPath, HttpContext.Current.Request.Url.LocalPath); | |
} | |
[TestCase("http://localhost:60653/Test.aspx", null, null, "localhost", 60653, "/", "/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/Test.aspx", "/", @"c:\InetPub\wwwRoot\", "localhost", 60653, "/", "/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/Test/Test.aspx", "/", @"c:\InetPub\wwwRoot\", "localhost", 60653, "/", "/Test/Test.aspx", @"c:\InetPub\wwwRoot\")] | |
[TestCase("http://localhost:60653/AppPath/Test.aspx", "/AppPath", @"c:\InetPub\wwwRoot\AppPath\", "localhost", 60653, "/AppPath", "/AppPath/Test.aspx", @"c:\InetPub\wwwRoot\AppPath\")] | |
[TestCase("http://localhost:60653/AppPath/Test.aspx", "/AppPath/", @"c:\InetPub\wwwRoot\AppPath\", "localhost", 60653, "/AppPath", "/AppPath/Test.aspx", @"c:\InetPub\wwwRoot\AppPath\")] | |
public void CanSimulateRequest(string url, string appPath, string physicalPath, string expectedHost, int expectedPort, string expectedAppPath, string expectedLocalPath, string expectedPhysicalPath) | |
{ | |
HttpSimulator simulator = new HttpSimulator(appPath, physicalPath); | |
simulator.SimulateRequest(new Uri(url)); | |
Assert.AreEqual(expectedHost, HttpContext.Current.Request.Url.Host); | |
Assert.AreEqual(expectedPort, HttpContext.Current.Request.Url.Port); | |
Assert.AreEqual(expectedAppPath, HttpContext.Current.Request.ApplicationPath); | |
Assert.AreEqual(expectedPhysicalPath, HttpContext.Current.Request.PhysicalApplicationPath); | |
Assert.AreEqual(expectedLocalPath, HttpContext.Current.Request.Url.LocalPath); | |
} | |
[TestCase("/", "/", @"c:\inetpub\wwwroot\")] | |
[TestCase("/Test/Test.aspx", "/", @"c:\inetpub\wwwroot\Test\Test.aspx")] | |
[TestCase("/Test/Blah/Test.aspx", "/", @"c:\inetpub\wwwroot\Test\Blah\Test.aspx")] | |
[TestCase("/Test", "/Test", @"c:\inetpub\wwwroot")] | |
[TestCase("/Test/", "/Test", @"c:\inetpub\wwwroot\")] | |
public void CanMapPath(string virtualPath, string appPath, string expectedMapPath) | |
{ | |
var url = new Uri("http://localhost/Test/Test.aspx"); | |
var simulator = new HttpSimulator(appPath, @"c:\inetpub\wwwroot\"); | |
simulator.SimulateRequest(url); | |
//Create a virtual path object. | |
var vpath = ReflectionHelper.Instantiate("System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", new Type[] { typeof(string) }, virtualPath); | |
Assert.IsNotNull(vpath); | |
var environment = HttpSimulatorTester.CallGetEnvironment(); | |
var vpathString = ReflectionHelper.InvokeProperty<string>(vpath, "VirtualPathString"); | |
var appVirtPath = ReflectionHelper.GetPrivateInstanceFieldValue<object>("_appVirtualPath", environment); | |
Assert.IsNotNull(appVirtPath); | |
Console.WriteLine("VPATH: " + vpath); | |
Console.WriteLine("App-VPATH: " + appVirtPath); | |
Console.WriteLine("vpath.VirtualPathString == '{0}'", vpathString); | |
var mapping = ReflectionHelper.InvokeNonPublicMethod<string>(typeof(HostingEnvironment), "GetVirtualPathToFileMapping", vpath); | |
Console.WriteLine("GetVirtualPathToFileMapping: --->{0}<---", (mapping ?? "{NULL}")); | |
var o = ReflectionHelper.GetPrivateInstanceFieldValue<object>("_configMapPath", environment); | |
Console.WriteLine("_configMapPath: {0}", o ?? "{null}"); | |
var mappedPath = ReflectionHelper.InvokeNonPublicMethod<string>(environment, "MapPathActual", vpath, false); | |
Console.WriteLine("MAPPED: " + mappedPath); | |
Assert.AreEqual(expectedMapPath, HttpContext.Current.Request.MapPath(virtualPath)); | |
} | |
[Test] | |
public void CanInstantiateVirtualPath() | |
{ | |
var virtualPathType = Type.GetType("System.Web.VirtualPath, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", true); | |
var constructor = virtualPathType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(string) }, null); | |
Assert.IsNotNull(constructor); | |
} | |
[Test] | |
public void CanGetHostingEnvironment() | |
{ | |
var environment = HttpSimulatorTester.CallGetEnvironment(); | |
Assert.IsNotNull(environment); | |
environment = HttpSimulatorTester.CallGetEnvironment(); | |
Assert.IsNotNull(environment); | |
} | |
[TestCase("/", "/")] | |
[TestCase("", "/")] | |
[TestCase("/test", "/test")] | |
[TestCase("test/", "/test")] | |
[TestCase("/test/", "/test")] | |
[TestCase("/test/////", "/test")] | |
[TestCase("////test/", "/test")] | |
[TestCase("/test/test////", "/test/test")] | |
[TestCase("/////test/test////", "/test/test")] | |
[TestCase("/////test///test////", "/test/test")] | |
public void CanNormalizeSlashes(string s, string expected) | |
{ | |
Assert.AreEqual(expected, HttpSimulatorTester.CallNormalizeSlashes(s)); | |
} | |
[Test] | |
public void CanStripTrailing() | |
{ | |
Assert.AreEqual(@"c:\blah\blah2", HttpSimulatorTester.CallStripTrailingBackSlashes(@"c:\blah\blah2\")); | |
} | |
} | |
internal class HttpSimulatorTester : HttpSimulator | |
{ | |
public static string CallNormalizeSlashes(string s) | |
{ | |
return NormalizeSlashes(s); | |
} | |
public static string CallStripTrailingBackSlashes(string s) | |
{ | |
return StripTrailingBackSlashes(s); | |
} | |
public static HostingEnvironment CallGetEnvironment() | |
{ | |
return GetHostingEnvironment(); | |
} | |
} | |
} |
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
using System; | |
using System.Reflection; | |
namespace Onboard.Tests.ZeroFriction.HttpMocking | |
{ | |
/// <summary> | |
/// Helper class to simplify common reflection tasks. | |
/// </summary> | |
public sealed class ReflectionHelper | |
{ | |
private ReflectionHelper() | |
{ | |
} | |
/// <summary> | |
/// Returns the value of the private member specified. | |
/// </summary> | |
/// <param name="fieldName">Name of the member.</param> | |
/// /// <param name="type">Type of the member.</param> | |
public static T GetStaticFieldValue<T>(string fieldName, Type type) | |
{ | |
var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static); | |
if (field != null) | |
{ | |
return (T)field.GetValue(type); | |
} | |
return default(T); | |
} | |
/// <summary> | |
/// Returns the value of the private member specified. | |
/// </summary> | |
/// <param name="fieldName">Name of the member.</param> | |
/// <param name="typeName"></param> | |
public static T GetStaticFieldValue<T>(string fieldName, string typeName) | |
{ | |
var type = Type.GetType(typeName, true); | |
var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static); | |
if (field != null) | |
{ | |
return (T)field.GetValue(type); | |
} | |
return default(T); | |
} | |
/// <summary> | |
/// Sets the value of the private static member. | |
/// </summary> | |
/// <param name="fieldName"></param> | |
/// <param name="type"></param> | |
/// <param name="value"></param> | |
public static void SetStaticFieldValue<T>(string fieldName, Type type, T value) | |
{ | |
var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static); | |
if (field == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find the private instance field '{0}'", fieldName)); | |
} | |
field.SetValue(null, value); | |
} | |
/// <summary> | |
/// Sets the value of the private static member. | |
/// </summary> | |
/// <param name="fieldName"></param> | |
/// <param name="typeName"></param> | |
/// <param name="value"></param> | |
public static void SetStaticFieldValue<T>(string fieldName, string typeName, T value) | |
{ | |
var type = Type.GetType(typeName, true); | |
var field = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static); | |
if (field == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find the private instance field '{0}'", fieldName)); | |
} | |
field.SetValue(null, value); | |
} | |
/// <summary> | |
/// Returns the value of the private member specified. | |
/// </summary> | |
/// <param name="fieldName">Name of the member.</param> | |
/// <param name="source">The object that contains the member.</param> | |
public static T GetPrivateInstanceFieldValue<T>(string fieldName, object source) | |
{ | |
var field = source.GetType().GetField(fieldName, BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance); | |
if (field != null) | |
{ | |
return (T)field.GetValue(source); | |
} | |
return default(T); | |
} | |
/// <summary> | |
/// Returns the value of the private member specified. | |
/// </summary> | |
/// <param name="memberName">Name of the member.</param> | |
/// <param name="source">The object that contains the member.</param> | |
/// <param name="value">The value to set the member to.</param> | |
public static void SetPrivateInstanceFieldValue(string memberName, object source, object value) | |
{ | |
var field = source.GetType().GetField(memberName, BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance); | |
if (field == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find the private instance field '{0}'", memberName)); | |
} | |
field.SetValue(source, value); | |
} | |
public static object Instantiate(string typeName) | |
{ | |
return Instantiate(typeName, null, null); | |
} | |
public static object Instantiate(string typeName, Type[] constructorArgumentTypes, params object[] constructorParameterValues) | |
{ | |
return Instantiate(Type.GetType(typeName, true), constructorArgumentTypes, constructorParameterValues); | |
} | |
public static object Instantiate(Type type, Type[] constructorArgumentTypes, params object[] constructorParameterValues) | |
{ | |
var constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, constructorArgumentTypes, null); | |
return constructor.Invoke(constructorParameterValues); | |
} | |
/// <summary> | |
/// Invokes a non-public static method. | |
/// </summary> | |
/// <typeparam name="TReturn"></typeparam> | |
/// <param name="type"></param> | |
/// <param name="methodName"></param> | |
/// <param name="parameters"></param> | |
/// <returns></returns> | |
public static TReturn InvokeNonPublicMethod<TReturn>(Type type, string methodName, params object[] parameters) | |
{ | |
var paramTypes = Array.ConvertAll(parameters, new Converter<object, Type>(delegate(object o) { return o.GetType(); })); | |
var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static, null, paramTypes, null); | |
if (method == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find a method with the name '{0}'", methodName), "method"); | |
} | |
return (TReturn)method.Invoke(null, parameters); | |
} | |
public static TReturn InvokeNonPublicMethod<TReturn>(object source, string methodName, params object[] parameters) | |
{ | |
var paramTypes = Array.ConvertAll(parameters, new Converter<object, Type>(delegate(object o) { return o.GetType(); })); | |
var method = source.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, paramTypes, null); | |
if (method == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find a method with the name '{0}'", methodName), "method"); | |
} | |
return (TReturn)method.Invoke(source, parameters); | |
} | |
public static TReturn InvokeProperty<TReturn>(object source, string propertyName) | |
{ | |
var propertyInfo = source.GetType().GetProperty(propertyName); | |
if (propertyInfo == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find a propertyName with the name '{0}'", propertyName), "propertyName"); | |
} | |
return (TReturn)propertyInfo.GetValue(source, null); | |
} | |
public static TReturn InvokeNonPublicProperty<TReturn>(object source, string propertyName) | |
{ | |
var propertyInfo = source.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance, null, typeof(TReturn), new Type[0], null); | |
if (propertyInfo == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find a propertyName with the name '{0}'", propertyName), "propertyName"); | |
} | |
return (TReturn)propertyInfo.GetValue(source, null); | |
} | |
public static object InvokeNonPublicProperty(object source, string propertyName) | |
{ | |
var propertyInfo = source.GetType().GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Instance); | |
if (propertyInfo == null) | |
{ | |
throw new ArgumentException(string.Format("Could not find a propertyName with the name '{0}'", propertyName), "propertyName"); | |
} | |
return propertyInfo.GetValue(source, 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
#region Disclaimer/Info | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
// Subtext WebLog | |
// | |
// Subtext is an open source weblog system that is a fork of the .TEXT | |
// weblog system. | |
// | |
// For updated news and information please visit http://subtextproject.com/ | |
// Subtext is hosted at SourceForge at http://sourceforge.net/projects/subtext | |
// The development mailing list is at [email protected] | |
// | |
// This project is licensed under the BSD license. See the License.txt file for more information. | |
/////////////////////////////////////////////////////////////////////////////////////////////////// | |
#endregion | |
using System; | |
using System.Collections.Specialized; | |
using System.IO; | |
using System.Text; | |
using System.Web.Hosting; | |
namespace Onboard.Tests.ZeroFriction.HttpMocking | |
{ | |
/// <summary> | |
/// Used to simulate an HttpRequest. | |
/// </summary> | |
public class SimulatedHttpRequest : SimpleWorkerRequest | |
{ | |
readonly string host; | |
readonly string verb; | |
readonly int port; | |
readonly string physicalFilePath; | |
private readonly NameValueCollection headers = new NameValueCollection(); | |
private readonly NameValueCollection formVariables = new NameValueCollection(); | |
Uri referrer; | |
public SimulatedHttpRequest(string applicationPath, string physicalAppPath, string physicalFilePath, string page, string query, TextWriter output, string host, int port, string verb) | |
: base(applicationPath, physicalAppPath, page, query, output) | |
{ | |
if (host == null) | |
{ | |
throw new ArgumentNullException("host", "Host cannot be null."); | |
} | |
if (host.Length == 0) | |
{ | |
throw new ArgumentException("Host cannot be empty.", "host"); | |
} | |
if (applicationPath == null) | |
{ | |
throw new ArgumentNullException("applicationPath", "Can't create a request with a null application path. Try empty string."); | |
} | |
this.host = host; | |
this.verb = verb; | |
this.port = port; | |
this.physicalFilePath = physicalFilePath; | |
} | |
internal void SetReferrer(Uri referer) | |
{ | |
this.referrer = referer; | |
} | |
/// <summary> | |
/// Returns the specified member of the request header. | |
/// </summary> | |
/// <returns> | |
/// The HTTP verb returned in the request | |
/// header. | |
/// </returns> | |
public override string GetHttpVerbName() | |
{ | |
return verb; | |
} | |
/// <summary> | |
/// Gets the name of the server. | |
/// </summary> | |
/// <returns></returns> | |
public override string GetServerName() | |
{ | |
return host; | |
} | |
public override int GetLocalPort() | |
{ | |
return this.port; | |
} | |
/// <summary> | |
/// Gets the headers. | |
/// </summary> | |
/// <value>The headers.</value> | |
public NameValueCollection Headers | |
{ | |
get | |
{ | |
return this.headers; | |
} | |
} | |
/// <summary> | |
/// Gets the format exception. | |
/// </summary> | |
/// <value>The format exception.</value> | |
public NameValueCollection Form | |
{ | |
get | |
{ | |
return formVariables; | |
} | |
} | |
/// <summary> | |
/// Get all nonstandard HTTP header name-value pairs. | |
/// </summary> | |
/// <returns>An array of header name-value pairs.</returns> | |
public override string[][] GetUnknownRequestHeaders() | |
{ | |
if (this.headers == null || this.headers.Count == 0) | |
{ | |
return null; | |
} | |
var headersArray = new string[this.headers.Count][]; | |
for (var i = 0; i < this.headers.Count; i++) | |
{ | |
headersArray[i] = new string[2]; | |
headersArray[i][0] = this.headers.Keys[i]; | |
headersArray[i][1] = this.headers[i]; | |
} | |
return headersArray; | |
} | |
public override string GetKnownRequestHeader(int index) | |
{ | |
if (index == 0x24) | |
{ | |
return referrer == null ? string.Empty : referrer.ToString(); | |
} | |
if (index == 12 && this.verb == "POST") | |
{ | |
return "application/x-www-form-urlencoded"; | |
} | |
return base.GetKnownRequestHeader(index); | |
} | |
/// <summary> | |
/// Returns the virtual path to the currently executing | |
/// server application. | |
/// </summary> | |
/// <returns> | |
/// The virtual path of the current application. | |
/// </returns> | |
public override string GetAppPath() | |
{ | |
var appPath = base.GetAppPath(); | |
return appPath; | |
} | |
public override string GetAppPathTranslated() | |
{ | |
var path = base.GetAppPathTranslated(); | |
return path; | |
} | |
public override string GetUriPath() | |
{ | |
var uriPath = base.GetUriPath(); | |
return uriPath; | |
} | |
public override string GetFilePathTranslated() | |
{ | |
return physicalFilePath; | |
} | |
/// <summary> | |
/// Reads request data from the client (when not preloaded). | |
/// </summary> | |
/// <returns>The number of bytes read.</returns> | |
public override byte[] GetPreloadedEntityBody() | |
{ | |
var formText = string.Empty; | |
foreach (string key in this.formVariables.Keys) | |
{ | |
formText += string.Format("{0}={1}&", key, this.formVariables[key]); | |
} | |
return Encoding.UTF8.GetBytes(formText); | |
} | |
/// <summary> | |
/// Returns a value indicating whether all request data | |
/// is available and no further reads from the client are required. | |
/// </summary> | |
/// <returns> | |
/// <see langword="true"/> if all request data is available; otherwise, | |
/// <see langword="false"/>. | |
/// </returns> | |
public override bool IsEntireEntityBodyIsPreloaded() | |
{ | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment