Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing Web Services - HttpContext

I want to write unit tests for a web service. I create my test project, reference my web project (not service reference, assembly reference), then write some code to test the web services - they work fine. However, there are some services which make sure the user is logged in to the web application by using HttpContext.Current.User.Identity.IsAuthenticated.

In the context of the tests, there is no such thing as HttpContext, so the tests always fail. How should these kinds of web services be unit tested?

like image 964
Brandon Montgomery Avatar asked Oct 26 '10 21:10

Brandon Montgomery


People also ask

What is HttpContext in Web API?

The HttpContext encapsulates all the HTTP-specific information about a single HTTP request. When an HTTP request arrives at the server, the server processes the request and builds an HttpContext object. This object represents the request which your application code can use to create the response.

Can we mock HttpContext?

HttpContextBase was added later to address HttpContext being difficult to mock. The two classes are basically unrelated ( HttpContextWrapper is used as an adapter between them). Fortunately, HttpContext itself is fakeable just enough for you do replace the IPrincipal (User) and IIdentity .

What is unit test in asp net core?

Unit testing involves testing a part of an application in isolation from its infrastructure and dependencies. When you unit test controller logic, only the content of a single action or method is tested, not the behavior of its dependencies or of the framework itself.


1 Answers

Here is a related discussion.

I stopped referencing HttpContext.Current directly. and use this class instead:

public class HttpContextFactory
{
    private static HttpContextBase m_context;
    public static HttpContextBase Current
    {
        get
        {
            if (m_context != null)
                return m_context;

            if (HttpContext.Current == null)
                throw new InvalidOperationException("HttpContext not available");

            return new HttpContextWrapper(HttpContext.Current);
        }
    }

    public static void SetCurrentContext(HttpContextBase context)
    {
        m_context = context;
    }
}

and use HttpContextFactory.Current instead of HttpContext.Current in our code.

Then you write this in your test:

        HttpContextFactory.SetCurrentContext(GetMockedHttpContext());

where GetMockedHttpContext() is from here and looks like this:

    private System.Web.HttpContextBase GetMockedHttpContext()
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var server = new Mock<HttpServerUtilityBase>();
        var user = new Mock<IPrincipal>();     
        var identity = new Mock<IIdentity>();

        context.Setup(ctx => ctx.Request).Returns(request.Object);
        context.Setup(ctx => ctx.Response).Returns(response.Object);
        context.Setup(ctx => ctx.Session).Returns(session.Object);
        context.Setup(ctx => ctx.Server).Returns(server.Object);
        context.Setup(ctx => ctx.User).Returns(user.Object);
        user.Setup(x => x.Identity).Returns(identity.Object);
        identity.Setup(id => id.IsAuthenticated).Returns(true);
        identity.Setup(id => id.Name).Returns("test");

        return context.Object;
    }

It uses a mocking framework called moq

In your test project you have to add a reference to System.Web and System.Web.Abstractions, where HttpContextBase is defined.

like image 178
Skuli Avatar answered Sep 17 '22 14:09

Skuli