Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit test a controller method that has the [Authorize] attribute applied?

I've searched stackoverflow and googled four a couple of hours and still not found any solution for my "trivial" problem.

If you write unit test for your filtered [Authorize] ActionResult, how do you solve the problem to fake that user is authenticated?

I have a lot of ActionResult methods that are filtered with [Authorize] and I want to test all of my ActionResult methods regardless if they are filtered with [Authorize] or not.

A simple example of what i mean:

[TestMethod] public void Create_Get_ReturnsView() {  // Arrange  var controller = new UserController();  // Act  var result = controller.Create();  // Assert  Assert.IsNotNull(result as ViewResult); }  [Authorize] public ActionResult Create() {  return View("Create"); } 

As of now the tests don't even hit the ActionResult method because of the [Authorize] filter, exception thrown is: System.NullReferenceException: Object reference not set to an instance of an object.

like image 894
Webking Avatar asked Dec 09 '09 22:12

Webking


People also ask

What happens if you apply the AllowAnonymous attribute to a controller action that already uses the Authorize attribute?

If you combine [AllowAnonymous] and any [Authorize] attribute, the [Authorize] attributes are ignored. For example if you apply [AllowAnonymous] at the controller level, any [Authorize] attributes on the same controller (or on any action within it) is ignored.

How does the Authorize attribute work?

If a user is not authenticated, or doesn't have the required user name and role, then the Authorize attribute prevents access to the method and redirects the user to the login URL. When both Roles and Users are set, the effect is combined and only users with that name and in that role are authorized.

Where can the Authorize attribute can be applied?

You can place the Authorize attribute on a controller or on individual actions inside the controller. When we place the Authorize attribute on the controller itself, the authorize attribute applies to all of the actions inside.


1 Answers

You need to mock a context for your controller. Try using Moq

Your arrange would then look like:

var controller = new UserController(); var mock = new Mock<ControllerContext>(); mock.SetupGet(x => x.HttpContext.User.Identity.Name).Returns("SOMEUSER"); mock.SetupGet(x => x.HttpContext.Request.IsAuthenticated).Returns(true); controller.ControllerContext = mock.Object; 

You should be able to then do your Act & Assert.

If you haven't already, I would highly recommend looking through NerdDinner as an example MVC site.

like image 181
Nate Avatar answered Sep 20 '22 06:09

Nate