Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Test Web Api 2 Mock User

I'm trying to mock the User.Identity in my Api Controller test.

This is my api method:

    [Route(Urls.CustInfo.GetCustomerManagers)]
    public HttpResponseMessage GetCustomerManagers([FromUri]int groupId = -1)
    {
        var user = User.Identity.Name;
        if (IsStaff(user) && groupId == -1)
        {
            return ErrorMissingQueryStringParameter;
        }
        ...
    }

I followed the suggestion in this post: Set User property for an ApiController in Unit Test to set the User property.

This is my test:

    [TestMethod]
    public void User_Without_Group_Level_Access_Call_GetCustomerManagers_Should_Fail()
    {
        Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), new[] {"managers"}); 
        var response = m_controller.GetCustomerManagers();

        Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
    }

But when the test is run, the User property is always null.

I even tried moving the line for setting the CurrentPrincipal into the api method just before calling User.Identity, but it's still null.

What am I doing wrong? If this approach doesn't work for web api 2, what's the best way to simulate/mock the User property?

Thanks!

like image 513
ozstudent Avatar asked Jun 11 '14 05:06

ozstudent


People also ask

Is it possible to unit test Web API?

You can either create a unit test project when creating your application or add a unit test project to an existing application. This tutorial shows both methods for creating a unit test project. To follow this tutorial, you can use either approach.

What is WebApplicationFactory?

WebApplicationFactory<TEntryPoint> is used to create a TestServer for the integration tests. TEntryPoint is the entry point class of the SUT, usually Program.


2 Answers

You can set the user in ControllerContext.RequestContext.Principal:

controller.ControllerContext.RequestContext.Principal = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), new[] {"managers"});

Or a shorthand equivalent:

controller.User = new GenericPrincipal(new GenericIdentity("Bob", "Passport"), new[] {"managers"});
like image 135
LostInComputer Avatar answered Oct 03 '22 05:10

LostInComputer


Though it is an old post, but I would like to add my thought as well.

If you only want to mock User Identity no need to use any mock framework, as you cannot mock User Identity using mock framework(not atleast with moq).

Simply assign the HttpContext.current property as below

HttpContext.Current = new HttpContext(
    new HttpRequest("", "http://localhost", ""),
    new HttpResponse(null)
);

And the HttpContext.Current.User be like this

HttpContext.Current.User = 
           new GenericPrincipal(
               new GenericIdentity("name"),
               new []{"manager","Admin"}
           );

Now the HttpContext.Current.User.Identity.Name will be available in controller of web api.

If you want to mock other property or object use moq or any other framework. But mocking HttpContext is as simple as the above.

like image 41
Iftikhar Ali Ansari Avatar answered Oct 03 '22 04:10

Iftikhar Ali Ansari