views:

524

answers:

2

Dear All,

I am trying to test the User.IsInRole("Administrator") in my application, and actually trying to assign the User Role to ("Administrator") so that my test will pass. I am using Scott Hanselman's MvcMockHelpers to do this, and at the moment I have the following test.

    [Test]
    public void Create_CanInsertNewArticleView_IsNotNull()
    {
        // Arrange
        var controller = new ArticleController();

        MockRepository mockRepo = new MockRepository();
        var fakeContext = MvcMockHelpers.FakeHttpContext(mockRepo, "~/Article/Create");
        fakeContext.User.IsInRole("Administrator");

        // Act
        Article fakeArticle = FakeObjects.ReturnFakeArticle();

        var result = controller.Create(fakeArticle) as ViewResult;

        // Assert
        Assert.IsNotNull(result);
    }

However the actual controller's User is null at the moment.

Can anyone help me out and tell me what the correct test should be, to User.IsInRole("Administrator")

Thanks for your help and time

Johann

+1  A: 

See this related answer for details.


Here's the code snippet from the other answer converted to Rhino Mocks:

var user = new GenericPrincipal(new GenericIdentity(string.Empty), null);
var httpCtx = MockRepository.GenerateStub<HttpContextBase>();
httpCtx.User = user;

var controllerCtx = new ControllerContext();
controllerCtx.HttpContext = httpCtx;

sut.ControllerContext = controllerCtx;
Mark Seemann
I also tried thisvar user = new GenericPrincipal(new GenericIdentity(string.Empty), null);var httpCtxStub = new Mock<HttpContextBase>();httpCtxStub.SetupGet(ctx => ctx.User).Returns(user);var controllerCtx = new ControllerContext();controllerCtx.HttpContext = httpCtxStub.Object;sut.ControllerContext = controllerCtx;but would not work, I think its Moq right? I am using Rhino Mocks
Johann
Yes, that other example uses Moq, but I have now edited my answer to include the code converted to Rhino Mocks.
Mark Seemann
thanks Markwhat is sut in this line?sut.ControllerContext = controllerCtx;
Johann
my new code:- var user = new GenericPrincipal(new GenericIdentity(string.Empty), null); user.IsInRole("Administrator"); var httpCtx = MockRepository.GenerateStub<HttpContextBase>(); httpCtx.User = user; var controllerCtx = new ControllerContext(); controllerCtx.HttpContext = httpCtx;However, when I go to the controller and try to test this:-if (!User.IsInRole("Administrator"))the User is still null
Johann
From the example in the link: SUT is the System Under Test, i.e. the Controller.
Mark Seemann
thanks Mark, that worked! Excellent
Johann
A: 

You'll have to mock an IPrincipal for your user object, set it up so that .IsInRole("Administrator") returns true, and then set your fakeContext up to return that IPrincipal for the.User property. It would be something like this:

EDIT: It turns out the OP is using Rhino Mocks, and the code I provided was for Moq. Here's an attempt att writing Rhino code, although I have never actually used Rhino myself. The original Moq code can be found below.

In Rhino Mocks, you'll want to add another helper method, or change the current one, so you have the following:

public static HttpContextBase FakeHttpContext(this MockRepository mocks, string url, IPrincipal user)
{
        // Do the same setup as Scott does...

        // ...and add this:
        SetupResult.For(context.User).Return(user);

        mocks.Replay(context);
        return context,
}

Then you declare and set up your IPrincipal mock object like this before the call to FakeHttpContext, and send the mock object in as the third parameter.


In Moq:

fakeContext = MvcMockHelpers.FakeHttpContext("~/Article/Create");
fakeUser = new Mock<IPrincipal>();
fakeUser.Expect(usr => usr.IsInRole(It.IsAny<String>())).Returns(true);
fakeContext.Expect(context => context.User).Returns(fakeUser.Object);

(Disclaimer: It was a while since I wrote a unit test, and this code has not been tested even for compilation errors. Hence, there might be some wrinkles that need to be ironed out before you can use this code, but you get the general idea...)

Tomas Lycken
I tried to add this SetupResult.For(fakeContext.User.IsInRole("Administrator")).Return(true);But its still failing on this line
Johann
AH, sorry! The arguments to the `.Expect()` methods should of course be lambda expressions. I don't recognize the syntax `SetupResult.For(...).Return(...)`, but it's probably the same thing there - you need a lambda. Try replacing `fakeContext` (in the code in your comment, not everywhere else) with `ctx => ctx`. If that doesn't work, try using the `.Expect()` methods I suggested instead.
Tomas Lycken
Hi Tomas,I tried your solution var fakeUser = mockRepo.StrictMock<IPrincipal>(); fakeUser.Expect(usr => usr.IsInRole(It.IsAny<String>())).Returns(true); fakeContext.Expect(context => context.User).Returns(fakeUser.Object);However I am getting a problem with It in fakeUser.Expect(usr => usr.IsInRole(It.IsAny<String>())).Returns(true);and also the Returns in fakeContext.Expect(context => context.User).Returns(fakeUser.Object);
Johann
Sorry - the code I provided is for Moq. I have never actually worked with Rhino Mocks (which you answered in the comment to the original post that you're using), but I'll give it a try. Edit coming up...
Tomas Lycken
Hi TomasSo I changed the Scott's FakeHttpContext as follows:- public static HttpContextBase FakeHttpContext(this MockRepository mocks, string url, IPrincipal user) { HttpContextBase context = FakeHttpContext(mocks); context.Request.SetupRequestUrl(url); SetupResult.For(context.User).Return(user); mocks.Replay(context); return context; }
Johann
Then I changed my code to the following :- var mockRepo = new MockRepository(); var user = new GenericPrincipal(new GenericIdentity(string.Empty), null); user.IsInRole("Administrator"); var httpCtx = MockRepository.GenerateStub<HttpContextBase>(); httpCtx.User = user; var fakeContext = MvcMockHelpers.FakeHttpContext(mockRepo, "~/Article/Create", user);
Johann
However now its throwing an error on this line of code in the FakeHttpContextSetupResult.For(context.User).Return(user);I am getting 'context.User' threw an exception of type 'System.NotImplementedException'
Johann
what type is it saying is not implementing? I think you need to use the `GenericPrincipal` class rather than `GenericIdentity`, but I'm not sure. As I said, I have never really used RhinoMocks, so whenever I need to mock a user I just mock the IPrincipal interface.
Tomas Lycken