Kåre Rasmussen
Kåre Rasmussen

Reputation: 913

Unit testing mvc model with HttpContext.Current.User.Identity.GetUserId()

In my MVC5 application, I have a Log entity, that is used to log any call to any controler. This log uses: HttpContext.Current.User.Identity.GetUserId() to determine the identity of the user accessing the controller.

public class Log
{
    public Log()
    {
        TS = DateTime.Now;
        UserId = HttpContext.Current.User.Identity.GetUserId();
    }

    [Required]
    public Int32 Id  { get; set; }
    public string UserId { get; set; }

    [Display(Name = "TS", ResourceType = typeof(Resources.Models.Log.Log))]
    [Required(ErrorMessageResourceType = typeof(Resources.Models.Log.Log), ErrorMessageResourceName = "RequiredTS")]
    public DateTime TS { get; set; }

    [Required]
    public short LogTypeId { get; set; }

    [Display(Name = "LogText", ResourceType = typeof(Resources.Models.Log.Log))]
    public string LogText { get; set; }

    public ApplicationUser User { get; set; }
}

When I try to unit test a controller and crating an instance of the log class I get this error:

threw exception: System.NullReferenceException: Object reference not set to an instance of an object. at DASU.Core.Models.Log..ctor()

I know this is because the context is not set.

So my question is how do I set the context, or how do I mock the context, so I can create the Log for my test?

Upvotes: 1

Views: 443

Answers (1)

Nkosi
Nkosi

Reputation: 247018

You should avoid coupling to HttpContext. Like suggested in the comments you could simplify your log my injecting the UserId into the dependent Log class

public class Log
{
    public Log(string userId)
    {
        TS = DateTime.Now;
        UserId = userId;
    }

    //...other code removed for brevity
}

or abstracting away the calls to HttpContext so that you can mock your abstract and inject that instead of trying and mock HttpContext

public interface IUserProvider {
    string GetUserId();
}

You production implementations can wrap calls to HttpContext and you can easily create mock implementations for your unit tests.

public class Log
{
    public Log(IUserProvider userProvider)
    {
        TS = DateTime.Now;
        UserId = userProvider.GetUserId();
    }

    //...other code removed for brevity
}

Upvotes: 1

Related Questions