在单元测试中设置HttpContext.Current.Application键

arn*_*off 5 c# asp.net asp.net-mvc asp.net-mvc-5

我有一个内部使用静态方法HttpContext.Current.Application来存储键值对并随后在整个应用程序中检索它的方法。

现在,我要做的是对该方法进行单元测试。我目前所拥有的是:

private const string Foo = "foobar";

[TestInitialize]
public void InitializeContext()
{
    HttpContext.Current = new HttpContext(new HttpRequest(null, "http://tempuri.org", null), new HttpResponse(null));
    HttpContext.Current.Application["fooKey"] = Foo;
}

[TestCleanup]
public void DisposeContext()
{
    HttpContext.Current = null;
}
Run Code Online (Sandbox Code Playgroud)

一切都很好,但是当我尝试在中投射该值时TestMethod,该值为null。

var fooValue = (string)HttpContext.Current.Application["fooKey"];
Run Code Online (Sandbox Code Playgroud)

显然,在我正在测试的方法中,该值也为null。

到目前为止,我尝试的是模拟上下文-效果也不佳。然后我看到了在SO上伪造的HTTP上下文解决方案,仍然无法正常工作。我什至尝试接受HttpApplicationStateBase/ HttpApplicationStateWrapper并通过它们进行工作,但这变得一团糟,我觉得有比这简单得多的解决方案。

arn*_*off 4

我最终做的是使用这个令人惊叹的库。对于那些想知道为什么没有任何效果的人,这个StackOverflow 问题解释了一个类似的问题(奇怪的是我在询问之前找不到它)。

根据杰夫斯特纳尔的回答:

HttpContext.Application 由您无法正常访问的私有单例提供。

您也许可以通过反射来设置它,但我个人甚至不会打扰。

相反,您应该将可测试代码与全局状态(如 HttpContext.Current)隔离:只需将您正在查找的值传递到您想要测试的方法中。

通过查看 Reflector 中的代码(或者在 .NET 源代码中,如果您已经下载了该代码),您可以清楚地看到问题:每次调用 HttpContext.Application get 访问器时,它都会返回一个新的 HttpApplicationState 实例,除非有某些情况(例如 ASP.NET)。 NET 框架)设置 HttpApplicationFactory._theApplicationFactory._state。

最终,我做了类似的事情:

using (HttpSimulator simulator = new HttpSimulator())
{
    simulator.SimulateRequest(new Uri("http://localhost/"));
    HttpContext.Current.Application.Add("fooKey", Foo);
    this.httpContext = HttpContext.Current;
}
Run Code Online (Sandbox Code Playgroud)

然后将保存的引用传递给我的方法。