HttpContext.Current is null when unit test

后端 未结 5 1670
太阳男子
太阳男子 2020-12-02 02:00

I have following web Api controller method.

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

相关标签:
5条回答
  • 2020-12-02 02:17

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

    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);

    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.

    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.

    Your original example has this

    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;
        }
    }
    

    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.

    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
            //.....
        }
    }
    
    0 讨论(0)
  • 2020-12-02 02:17

    I have added FakeHttpContext nuget package and it worked for me.

    0 讨论(0)
  • 2020-12-02 02:21

    This is by design and it's always null. But there is a FakeHttpContext project on Nuget that simply you can use it.

    To install FakeHttpContext, run the following command in the Package Manager Console (PMC)

    Install-Package FakeHttpContext 
    

    And then use it like this:

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

    Visit https://www.nuget.org/packages/FakeHttpContext to install the package

    See examples on Github: https://github.com/vadimzozulya/FakeHttpContext#examples

    Hope this will help :)

    0 讨论(0)
  • 2020-12-02 02:23

    All you need is

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

    From unit-testing-controllers-in-web-api

    0 讨论(0)
  • 2020-12-02 02:24

    you can try to add FakeHttpContext nuget package.

    0 讨论(0)
提交回复
热议问题