It is too complicated to simulate HttpContext for testing-driven development on the Web.
The moq framework provides powerful simulation capabilities. However, you still need to manually simulate an HttpContext object.
For this reason, I wrote a method to complete the job. Log4Net is also used to output its working conditions.
View sourceprint?
01 /// <summary>
02 // create a context simulation object
03 // at least support required
04 // Request
05 // AppRelativeCurrentExecutionFilePath,
06 // ApplicationPath
07 // PathInfo
08 // Response
09 // ApplyAppPathModifier
10 /// </summary>
11 /// <returns> </returns>
12 private Moq. Mock <System. Web. HttpContextBase> CreateHttpContext ()
13 {
14 log4net. ILog log = log4net. LogManager. GetLogger ("CreateHttpContext ");
15
16 string ApplicationPath = "/";
17 string PathInfo = "";
18 string AppRelativeCurrentExecutionFilePath = "~ /";
19
20 var contextMock = new Moq. Mock <System. Web. HttpContextBase> ();
21
22 contextMock
23. Setup (c => c. Request. AppRelativeCurrentExecutionFilePath)
24. Returns (AppRelativeCurrentExecutionFilePath)
25. Callback () => log. Info ("Calling AppRelativeCurrentExecutionFilePath "));
26
27 contextMock
28. Setup (c => c. Request. ApplicationPath)
29. Returns (ApplicationPath)
30. Callback () => log. Info ("Calling ApplicationPath "));
31 contextMock. Setup (rc => rc. Request. PathInfo)
32. Returns (PathInfo)
33. Callback () => log. Info ("Calling PathInfo "));
34
35 contextMock
36. Setup (rc => rc. Response. ApplyAppPathModifier (Moq. It. IsAny <string> ()))
37. Returns (string s) => s)
38. Callback (string s) => log. InfoFormat ("Calling ApplyAppPathModifier: {0}.", s ));
39
40 return contextMock;
41}
Although this method has been able to complete the test I need, I hope to refine it to get a more general Mock method.
Soon, I found that this job was introduced by Scott Hanselman a long time ago, and I even wrote about how to provide IT UNDER DIFFERENT Mock frameworks. But the author of The moq version is not him, but another person, Daniel Cazzulino, which you can find here: Author Cazzulino's blog: http://blogs.clariusconsulting.net/kzu/
However, his article was written in 2008, and he is too old. At that time, the MVC Preview2 and moq were born at that time. It seems that I am too ignorant.
After returning to our topic, after such a long period of time, moq has made some changes. After using the latest moq syntax, we found that its code could not pass the test.
Compared with me, I found that the ApplyAppPathModifier method in Response is missing, and it will be normal after it is added.
The following is the modified Code, hoping to make it easier for you.
View sourceprint?
001 using System;
002 using System. Web;
003 using System. Text. RegularExpressions;
004 using System. IO;
005 using System. Collections. Specialized;
006 using System. Web. Mvc;
007 using System. Web. Routing;
008
009 using Moq;
010
011 namespace UnitTests
012 {
013 public static class MvcMockHelpers
014 {
015 public static HttpContextBase FakeHttpContext ()
016 {
017 var context = new Mock <HttpContextBase> ();
018 var request = new Mock <HttpRequestBase> ();
019 var response = new Mock <HttpResponseBase> ();
020 var session = new Mock <HttpSessionStateBase> ();
021 var server = new Mock <HttpServerUtilityBase> ();
022
023 // The ApplyAppPathModifier method of Response must be set
024 response
025. Setup (rsp => rsp. ApplyAppPathModifier (Moq. It. IsAny <string> ()))
026. Returns (string s) => s );
027
028 context. Setup (ctx => ctx. Request). Returns (request. Object );
029 context. Setup (ctx => ctx. Response). Returns (response. Object );
030 context. Setup (ctx => ctx. Session). Returns (session. Object );
031 context. Setup (ctx => ctx. Server). Returns (server. Object );
032
033 return context. Object;
034}
035
036 public static HttpContextBase FakeHttpContext (string url)
037 {
038 HttpContextBase context = FakeHttpContext ();
039 context. Request. SetupRequestUrl (url );
040 return context;
041}
042
043 // an extension method of Controller
044 public static void SetFakeControllerContext (this Controller controller)
045 {
046 var httpContext = FakeHttpContext ();
047 ControllerContext context = new ControllerContext (new RequestContext (httpContext, new RouteData (), controller );
048 controller. ControllerContext = context;
049}
050
051 static string GetUrlFileName (string url)
052 {
053 if (url. Contains ("? "))
054 return url. Substring (0, url. IndexOf ("? "));
055 else
056 return url;
057}
058
059 static NameValueCollection GetQueryStringParameters (string url)
060 {
061 if (url. Contains ("? "))
062 {
063 NameValueCollection parameters = new NameValueCollection ();
064
065 string [] parts = url. Split ("? ". ToCharArray ());
066 string [] keys = parts [1]. Split ("&". ToCharArray ());
067
068 foreach (string key in keys)
069 {
070 string [] part = key. Split ("=". ToCharArray ());
071 parameters. Add (part [0], part [1]);
072}
073
074 return parameters;
075}
076 else
077 {
078 return null;
079}
080}
081
082 // extended HttpRequestBase
083 public static void SetHttpMethodResult (this HttpRequestBase request, string httpMethod)
084 {
085 Mock. Get (request)
086. Setup (req => req. HttpMethod)
087. Returns (httpMethod );
088}
089
090 // set the request address
091 public static void SetupRequestUrl (this HttpRequestBase request, string url)
092 {
093 log4net. ILog log = log4net. LogManager. GetLogger ("CreateHttpContext ");
094
095 if (url = null)
096 throw new ArgumentNullException ("url ");
097
098 if (! Url. StartsWith ("~ /"))
099 throw new ArgumentException ("Sorry, we recommend CT a virtual url starting \"~ /\".");
100
101 var mock = Mock. Get (request );
102
103 mock. Setup (req => req. QueryString)
104. Returns (GetQueryStringParameters (url ));
105 mock. Setup (req => req. AppRelativeCurrentExecutionFilePath)
106. Returns (GetUrlFileName (url ))
107. Callback () => log. Info ("Calling AppRelativeCurrentExecutionFilePath "));
108
109
110 mock. Setup (req => req. PathInfo)
111. Returns (string. Empty );
112
113}
114
115}
116}