unit testing时HttpContext.Current为null

我有以下web Api控制器方法。

当我通过web运行此代码时, HttpContext.Current never null并给出所需的值。

 public override void Post([FromBody]TestDTO model) { var request = HttpContext.Current.Request; var testName = request.Headers.GetValues("OS Type")[0]; // more code } 

但是,当我从Unit Test调用此方法时, HttpContext.Current is always null.

我如何解决它?

在unit testing期间, HttpContext始终为null因为它通常由IIS填充。 你有几个选择。

当然,你可以模拟HttpContext ,(你不应该真的这样做 – 不要模仿HttpContext !!!!他不喜欢被嘲笑!),. 你应该尝试远离代码中与HttpContext紧密耦合。 尝试将其约束到一个中心区域(SRP);

而是弄清楚你想要实现的function是什么,并围绕它设计一个抽象。 这将允许您的代码更加可测试,因为它与HttpContext没有紧密耦合。

根据您的示例,您希望访问标头值。 这只是在使用HttpContext时如何改变思路的一个例子。

你原来的例子有这个

 var request = HttpContext.Current.Request; var testName = request.Headers.GetValues("OS Type")[0]; 

当你在寻找这样的东西

 var testName = myService.GetOsType(); 

然后创建一个提供该服务的服务

 public interface IHeaderService { string GetOsType(); } 

这可能有一个具体的实现

 public class MyHeaderService : IHeaderService { public string GetOsType() { var request = HttpContext.Current.Request; var testName = request.Headers.GetValues("OS Type")[0]; return testName; } } 

现在在您的控制器中,您可以拥有抽象而不是与HttpContext紧密耦合

 public class MyApiController : ApiController { IHeaderService myservice; public MyApiController(IHeaderService headers) { myservice = headers; } public IHttpActionResult Post([FromBody]TestDTO model) { var testName = myService.GetOsType(); // more code } } 

您可以稍后注入具体类型以获得所需的function。

为了测试你然后交换依赖项来运行你的测试。

如果测试中的方法是Post()方法,则可以创建伪依赖项或使用模拟框架

 [TestClass] public class MyTestClass { public class MyFakeHeaderService : IHeaderService { string os; public MyFakeHeaderService(string os) { this.os = os; } public string GetOsType() { return os; } } [TestMethod] public void TestPostMethod() { //Arrange IHeaderService headers = new MyFakeHeaderService("FAKE OS TYPE"); var sut = new MyApiController(headers); var model = new TestDTO(); //Act sut.Post(model); //Assert //..... } } 

这是设计的,它总是空的。 但是FakeHttpContext上有一个FakeHttpContext项目,只需你可以使用它。

要安装FakeHttpContext,请在程序包管理器控制台(PMC)中运行以下命令

 Install-Package FakeHttpContext 

然后像这样使用它:

 using (new FakeHttpContext()) { HttpContext.Current.Session["mySession"] = "This is a test"; } 

访问https://www.nuget.org/packages/FakeHttpContext/

希望这会有所帮助:)

我添加了FakeHttpContext nuget包,它对我有用。

所有你需要的是

 controller.Request = new HttpRequestMessage(); controller.Configuration = new HttpConfiguration(); 

来自unit-testing-controllers-in-web-api