单元测试时HttpContext.Current为null

时间:2016-07-03 13:34:42

标签: c# unit-testing asp.net-web-api

我有以下网络Api控制器方法。

当我通过网络运行此代码时,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 TestHttpContext.Current is always null.

调用此方法时

我该如何解决?

5 个答案:

答案 0 :(得分:18)

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

当然,你可以嘲笑HttpContext,(你不应该这么做 - Don't mock 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
        //.....
    }
}

答案 1 :(得分:5)

  

这是设计使然,它始终为空。但是 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

希望这会有所帮助:)

答案 2 :(得分:1)

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

答案 3 :(得分:1)

您可以尝试添加FakeHttpContext nuget包。

答案 4 :(得分:-1)

你需要的只是

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

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