Scenario: A. Net HTTP module was recently tested, which is used for URL rewriting. At the beginning, the progress was quite smooth, because the method parameters in the module were basically strings. Later, the module was restructured and all the parameters were changed to httpcontext, this directly caused the original unit tests to fail and then started to get httpcontext.
1. Use ASP. NET unit test provided by Visual Studio
At the beginning, I looked at the tested code. Although httpcontext is used, there are many places that I can go around. This means that httpcontext is only a parameter required for the above name, as long as it is not null, it does not affect my testing, so I use ASP. net unit test method to obtain an httpcontext. This method is the easiest to implement, but there are some problems that will be mentioned later.
Create a new web project, and then mount the tested HTTP module to the new web project. Then you can configure ASP. Net unit tests to transform the original unit tests into an ASP. NET unit test. Follow these steps to add the following attributes before the test method:
123 |
[HostType("ASP.NET")][UrlToTest("http://localhost:6988/Default.aspx")][AspNetDevelopmentServerHost("D:\\MS_Code\\Public\\UrlRouter.WebTest", "/")] |
[Urltotest]-This attribute specifies the URL when the unit test is run.
[Hosttype]-generally, the unit test runs under the host process of vstest, so there is no httpcontext. If it is used as an ASP. net unit test, it must be in ASP.. Net host process
[Aspnetdevelopmentserverhost]-since I use ASP. NET development server as the testing host server, rather than IIS, I need to set this attribute to specify the full path of the Web application. Here, I need to point the directory to the path of the newly created web project. In this way, you can directly use httpcontext. Current in the unit test to obtain an httpcontext.
1234567891011 |
[[TestMethod][HostType("ASP.NET")][AspNetDevelopmentServerHost("D:\\MS_Code\\Public\\UrlRouter.WebTest", "/")][UrlToTest("http://localhost:6988/Default.aspx")]public void Fuseaction_PUT(){ handler = new UrlMapHandler(HttpContext.Current); Assert.IsNotNull(handler); result = handler.ExecuteUrlMap(); StringAssert.Contains(result.Url, "expected string");} |
In this way, the problem of httpcontext is solved, but the following problems may occur:
- Uncontrollable content of httpcontext
- You need to run ASP. NET development server
- Debugging is not allowed.
2. directly create an httpcontext instance
Based on the three shortcomings mentioned above, I decided to create an httpcontext directly to solve the problem. Fortunately, httpcontext has a public constructor. This constructor must accept an httpworkerrequest as a parameter. httpworkerrequest is an abstract class and cannot be instantiated directly. However, the good news is that, microsoft has a simple class "simpleworkerrequest", which implements the httpworkerrequest class. Below is a simple code
1234 |
TextWriter tw = new StringWriter();HttpWorkerRequest wr = new SimpleWorkerRequest("default.aspx", "friendId=1300000000", tw);HttpContext.Current = new HttpContext(wr); |
In this way, httpcontext can be used in unit testing, with the following benefits:
- The content of httpcontext can be controlled. For URL rewriting, The Request Path and querystring will be concerned. These two parameters can be passed as parameters when simpleworkerrequest is instantiated.
- ASP. NET development server is not required. This is important because it can meet the requirements of a self-contained unit test.
- Debuggable
3. Improved Solution
At this point, the world is wonderful and the test is going smoothly. Not long before, I encountered another problem. This URL rewriting module also applied a rule engine, which performed a lot of operations on host judgment. Unfortunately, httpcontext created in the previous method, which returns the request. in the URL, the host will always be 127.0.0.1, which is very depressing. At this time, all the people who are doing. NET will need to use the Dragon Sword !. Net reflector, use reflector to open system. web. DLL, find system. web. hosting namespace, find the simpleworkerrequest class, and find the getlocaladdress () method in it, and find that there is a hard-Code address: 127.0.0.1; well, you know where the problem is, handwritten a new class that inherits simpleworkerrequest and then overwrites its getlocaladdress () method:
123456789101112131415 |
public class MyWorkerRequest : SimpleWorkerRequest{ private string localAdd = string.Empty; public MyWorkerRequest(string page, string query, TextWriter output, string address) : base(page, query, output) { this.localAdd = address; } public override string GetLocalAddress() { return this.localAdd; }} |
In this way, httpcontext is instantiated like this:
1234567 |
Thread.GetDomain().SetData(".appPath", "c:\\inetpub\\wwwroot\\webapp\\");Thread.GetDomain().SetData(".appVPath", "/");TextWriter tw = new StringWriter();String address = "home.myspace.cn";HttpWorkerRequest wr = new MyWorkerRequest("default.aspx", "friendId=1300000000", tw, address);HttpContext.Current = new HttpContext(wr); |
It should be noted that the settings for. apppath and. appvpath are required, because these two values are taken in the simpleworkerrequest constructor.
After such transformation, the test needs have been basically met.
Summary:
- It took more than a day to solve this problem. Later, I found that the solution was in my subscribed blog. In the future, I would like to find a Google Reader.
- Multiple Use of. Net reflector. Visual Studio often allows you to view meta data. Meta data is useless to us at all. It is better to use reflector.