Search code examples
authenticationrhino-mocksidentityhttpcontext

Set up a result for a composite part of a mock


We try to mock a HttpContext of an MVC 3 application using RhinoMocks Looks like this:

HttpContextBase context = mocks.StrictMock<HttpContextBase>();
HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();
IPrincipal user = mocks.StrictMock<IPrincipal>(); 
HttpCookieCollection cookies = new HttpCookieCollection();
IIdentity identity = mocks.StrictMock<IIdentity>();
HttpResponseBase response = mocks.PartialMock<HttpResponseBase>();

SetupResult.For(response.Cookies).Return(cookies);
SetupResult.For(context.User).Return(user);
SetupResult.For(user.Identity).Return(identity);
SetupResult.For(context.Request).Return(request);
SetupResult.For(context.Response).Return(response);
mocks.Replay(context);

In my test I need the user to be authenticated so I added following:

var identity = context.User.Identity;
mocks.BackToRecord(identity);
SetupResult.For(identity.IsAuthenticated).Return(true).Repeat.Any();
mocks.Replay(identity);

This however results in a "The result for IIdentity.get_IsAuthenticated(); has already been setup." exception to be thrown.

Why? What do I need to do to make the authenticated settable in my tests?


Solution

  • It's been a long time since I used the record/replay semantics vs. the AAA (Arrange/Act/Assert) syntax, but try doing the SetupResult on just the identity mock:

    mocks.BackToRecord(identity);
    SetupResult.For(identity.IsAuthenticated).Return(true).Repeat.Any();
    mocks.Replay(identity);
    

    NEW ANSWER

    Get rid of the .Repeat.Any(). I think since this is a property, you just need to set the return value. Rhino.Mocks will always return that value -- you don't need to tell it to repeat. I did a quick test and was getting the same error you got, but as soon as I removed the .Repeat.Any(), it worked.