繁体   English   中英

单元测试时 HttpContext.Current 为空

[英]HttpContext.Current is null when unit test

我有以下 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.

我如何解决它?

在单元测试期间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()方法,您可以创建一个假依赖或使用模拟框架

[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的NuGet项目,只需你可以使用它。

要安装 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

希望这会有所帮助:)

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

您可以尝试添加 FakeHttpContext nuget 包。

所有你需要的是

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM