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

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

问题描述

我有以下 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 Test 调用此方法时,HttpContext.Current 始终为 null.

However, when I call this method from Unit Test, HttpContext.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,(您实际上不应该这样做 - 不要嘲笑 HttpContext!!!!他不喜欢被嘲笑!),.你真的应该尽量避免在你的代码中与 HttpContext 紧密耦合.尝试将其限制在一个中心区域 (SRP);

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 为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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