HttpContext.单元测试时Current为null

本文关键字:null Current 单元测试 HttpContext | 更新日期: 2023-09-27 17:54:08

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

当我通过web运行此代码时,HttpContext.Currentnever 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.

我如何修复它?

HttpContext.单元测试时Current为null

在单元测试期间,HttpContext总是null,因为它通常由IIS填充。你有几个选择。

当然,您可以模拟HttpContext,(您不应该真正这样做- 不要模拟HttpContext!!!!他不喜欢被嘲笑!您应该尽量避免在代码中使用HttpContext进行紧密耦合。尝试将其限制在一个中心区域(SRP);

相反,弄清楚你想要实现的功能是什么,并围绕它设计一个抽象。这将允许您的代码更具可测试性,因为它不那么紧密地耦合到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
    }    
}

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

对于测试,然后交换依赖项来运行测试。

如果被测试的方法是你的Post()方法,你可以创建一个假的依赖或者使用一个mock框架

[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
        //.....
    }
}

这是设计的,它总是空的。但是在Nuget上有一个FakeHttpContext项目,你可以简单地使用它。

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

Install-Package FakeHttpContext 

然后像这样使用:

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

访问https://www.nuget.org/packages/FakeHttpContext安装包

参见Github上的示例:https://github.com/vadimzozulya/FakeHttpContext#examples

希望对你有帮助

你所需要的是

controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
从unit-testing-controllers-in-web-api