我发现这段代码是为了进行单元测试而进行模拟请求。我正在尝试设置用户主机地址,但我不清楚如何使用此代码中概述的相同方法来实现这一目标。我认为这必须通过反射来完成,因为我发现不允许设置标题。有什么想法吗?
public static HttpContext FakeHttpContext()
{
var httpRequest = new HttpRequest("", "http://fakurl/", "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);
var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
new HttpStaticObjectsCollection(), 10, true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard,
new[] { typeof(HttpSessionStateContainer) },
null)
.Invoke(new object[] { sessionContainer });
httpContext.Request.Headers["REMOTE_ADDR"] = "XXX.XXX.XXX.XXX"; // not allowed
return httpContext;
}
我也尝试了这个模拟库:
https://gist.github.com/rally25rs/1578697
按用户主机地址仍然是只读的。
我发现的最佳方法是拥有某种实现IContextService接口的ContextService。 此类/接口对可以执行您需要的任何操作。关键是,如果您在单元测试(如 MOQ)中使用模拟框架,那么您可以连接模拟上下文服务以返回特定的 IP 地址。
这篇 StackOverflow 帖子有一些很好的指针:Moq:单元测试依赖于 HttpContext 的方法。
更新:
你找到的StackOverflow帖子也是一个很好的帖子:如何在"模拟"的BaseHttpContext上设置IP(UserHostAddress)?
我发现通常我只需要上下文/请求/响应对象中的几个属性,所以我经常滚动我自己的较小变体:
public class ContextService : IContextService
{
public string GetUserHostAddress()
{
return HttpContext.Current.Request.UserHostAddress;
}
}
public interface IContextService
{
string GetUserHostAddress();
}
使用该类/接口组合,我可以使用 Moq 来连接虚假服务:
var contextMock = new Moq.Mock<IContextService>();
contextMock.Setup(c => c.GetUserHostAddress()).Returns("127.0.0.1");
现在每次打电话contextMock.GetUserHostAddress()
,都会得到"127.0.0.1"。 自己滚动可能是一个很好的学习体验,特别是如果你不需要一个成熟的(或尽可能完整的)HttpContext模拟的所有花里胡哨的东西。