单元测试时HttpContext.Current为null

sim*_*ada 7 c# unit-testing asp.net-web-api

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

当我通过网络运行此代码时,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

}
Run Code Online (Sandbox Code Playgroud)

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

我如何解决它?

Nko*_*osi 21

在单元测试期间,HttpContext始终null通常由IIS填充.你有几个选择.

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

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

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

你原来的例子有这个

var request = HttpContext.Current.Request;
var testName = request.Headers.GetValues("OS Type")[0];
Run Code Online (Sandbox Code Playgroud)

当你在寻找这样的东西

var testName = myService.GetOsType();
Run Code Online (Sandbox Code Playgroud)

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

public interface IHeaderService {
    string GetOsType();
}
Run Code Online (Sandbox Code Playgroud)

这可能有一个具体的实现

public class MyHeaderService : IHeaderService {

    public string GetOsType() {
        var request = HttpContext.Current.Request;
        var testName = request.Headers.GetValues("OS Type")[0];
        return testName;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在您的控制器中,您可以拥有抽象而不是紧密耦合 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

    }    
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果测试方法是您的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
        //.....
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 2014 年的一个很好的参考:https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection 这有一些其他重要的细节,例如控制反转,它允许您调用您在控制器实例化期间的自定义上下文类。 (2认同)

Ahm*_*yan 5

这是设计的,它总是空的.但是NugetFakeHttpContext上有一个项目就是你可以使用它.

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

Install-Package FakeHttpContext 
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

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

访问https://www.nuget.org/packages/FakeHttpContext以安装该软件包

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

希望这会有所帮助:)