27

I'd like to write (in c#) a unit-test for an MVC controller action which might return one view or the other, depending on whether the request is authenticated. How can this be done?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Mats
  • 14,902
  • 33
  • 78
  • 110

2 Answers2

37

You can mock your Request. Something like this (Moq using):

var request = new Mock<HttpRequestBase>();
request.SetupGet(x => x.IsAuthenticated).Returns(true); // or false

var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);

var controller = new YourController();
controller.ControllerContext = 
       new ControllerContext(context.Object, new RouteData(), controller);

// test

ViewResult viewResult = (ViewResult)controller.SomeAction();

Assert.True(viewResult.ViewName == "ViewForAuthenticatedRequest");
SteveC
  • 15,808
  • 23
  • 102
  • 173
eu-ge-ne
  • 28,023
  • 6
  • 71
  • 62
17

Using mocking and dependency injection. The following assumes that you're checking that it is authenticated and then accessing the user object to get the user's id. Uses RhinoMocks.

// mock context variables
var username = "user";
var httpContext = MockRepository.GenerateMock<HttpContextBase>();
var request = MockRepository.GenerateMock<HttpRequestBase>();
var identity = MockRepository.GenerateMock<IIdentity>();
var principal = MockRepository.GenerateMock<IPrincipal>();

httpContext.Expect( c => c.Request ).Return( request ).Repeat.AtLeastOnce();
request.Expect( r => r.IsAuthenticated ).Return( true ).Repeat.AtLeastOnce();
httpContext.Expect( c => c.User ).Return( principal ).Repeat.AtLeastOnce();
principal.Expect( p => p.Identity ).Return( identity ).Repeat.AtLeastOnce();
identity.Expect( i => i.Name ).Return( username ).Repeat.AtLeastOnce();

var controller = new MyController();
// inject context
controller.ControllerContext = new ControllerContext( httpContext,
                                                      new RouteData(),
                                                      controller );

var result = controller.MyAction() as ViewResult;

Assert.IsNotNull( result );

// verify that expectations were met
identity.VerifyAllExpectations();
principal.VerifyAllExpectations();
request.VerifyAllExpectations();
httpContext.VerifyAllExpectations();
SteveC
  • 15,808
  • 23
  • 102
  • 173
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 1
    thanks for your answer which i'm sure is working excellently. since I've tested eu-ge-ne answer (which works fine for me) and he was a little faster with the response, I marked his answer. no offense. have a good day. ;) – Mats Jul 10 '09 at 06:40
  • 1
    Not a problem. It's really the same answer. I only left mine because it shows how to mock the principal/identity in case you need to get at the username -- or the IsInRole method on the principal, which I haven't shown. – tvanfosson Jul 10 '09 at 10:47