单元测试时HttpContext.Current为null [英] HttpContext.Current is null when unit test

查看:160
本文介绍了单元测试时HttpContext.Current为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have following web Api controller method.

当我通过网络运行此代码时,HttpContext.Currentnever null并提供所需的值.

When I run this code through web, HttpContext.Current is never null and give desired value.

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.

我该如何解决?

推荐答案

在单元测试期间,HttpContext始终为null,因为它通常由IIS填充.您可以选择一些解决方案.

During unit tests HttpContext is always null as it is usually populate by IIS. You have a few options around this.

当然,您可以嘲笑HttpContext,(您实际上不应该这样做-

Sure, you could mock the HttpContext, (which you shouldn't really do - Don't mock HttpContext!!!! He doesn't like to be mocked!),. You should really try to stay away from tight coupling with HttpContext all over your code. Try constraining it to one central area (SRP);

相反,要弄清楚您要实现的功能以及围绕该功能设计一个抽象.这将使您的代码更具可测试性,因为它与HttpContext紧密耦合.

Instead figure out what is the functionality you would like to achieve and design an abstraction around that. This will allow for your code to be more testable as it is not so tightly coupled to HttpContext.

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

Based on your example you are looking to access header values. This is just an example of how to change your thinking when it comes to using HttpContext.

您的原始示例有此

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

当您正在寻找类似的东西

When you are looking for something like this

var testName = myService.GetOsType();

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

Well then create a service that provides that

public interface IHeaderService {
    string GetOsType();
}

可能有具体的实现方式,例如

which could have a concrete implementation like

public class MyHeaderService : IHeaderService {

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

现在,您可以在控制器中进行抽象了,而不必与HttpContext

Now in your controller you can have your abstraction instead of having tight coupling to 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

    }    
}

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

You can later inject your concrete type to get the functionality you want.

对于测试,您然后交换依赖关系以运行测试.

For testing you then swap dependencies to run your test.

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

If the method under test is your Post() method you can create a fake dependency or use a mocking framework

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

这篇关于单元测试时HttpContext.Current为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆