سؤال

I'm trying to run some tests on my MVC application but I've been experiencing a world of trouble getting it to work. I'll try to get right to the point:

I'm using RhinoMocks to try something like this:

Setup:

MockRepository mocks = new MockRepository();
HttpContextBase _mockContext = mocks.FakeHttpContext();
mocks.SetFakeControllerContext(new LoginController());
HttpApplicationStateBase appState = MockRepository.GenerateStub<HttpApplicationStateBase>();
_mockContext.Expect(mc => mc.Application).Return(appState);
HttpContext.Current = _mockContext.ApplicationInstance.Context;

Here's the FakeHttpContext() method:

public static HttpContextBase FakeHttpContext(this MockRepository mocks)
{
    HttpApplication app = mocks.PartialMock<HttpApplication>();

    HttpContextBase context = mocks.PartialMock<HttpContextBase>();
    HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();
    HttpResponseBase response = mocks.PartialMock<HttpResponseBase>();
    HttpSessionStateBase session = mocks.PartialMock<HttpSessionStateBase>();
    HttpServerUtilityBase server = mocks.PartialMock<HttpServerUtilityBase>();

    SetupResult.For(context.ApplicationInstance).Return(app);

    SetupResult.For(context.Request).Return(request);
    SetupResult.For(context.Response).Return(response);
    SetupResult.For(context.Session).Return(session);
    SetupResult.For(context.Server).Return(server);

    mocks.Replay(context);
    return context;
}

I really need to access HttpContextBase.Request.AppRelativeCurrentExecutionFilePath but it's always returned as null. The same goes for HttpContext.Current.Request.RequestContext.

Can anybody help me out here? It's safe to say I'm desperate at this point.

هل كانت مفيدة؟

المحلول

First of all, try avoid using HttpContext.Current as using a static method makes it much harder to test as you have found out now. If you are using a dependency injection framework, inject HttpContextBase into your constructor.

For your actual problem, in FakeHttpContext() try to change

 HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();

to

 HttpRequestBase request = mocks.GenerateStub<HttpRequestBase>();

and then in your test you can do something like this:

_mockContext.Request.Stub(x=> x.AppRelativeCurrentExecutionFilePath).Return("foo");
var result = object.DoSomething();
Assert.AreEqual("foo",result);

I don't think it's quite useful to do partial mocking on the HttpContext as you will be testing the framework instead (i.e. test that the framework returns you the correct value X based on value Y and Z in the HttpContext)

Another alternative is to create a wrapper class around HttpContextBase that will return you computed values. E.g. HttpContextBaseWrapper.AppRelativeCurrentExecutionFilePath(), HttpContextBaseWrapper.RequestIpAddress(). This will make testing ALL your other classes less complicated as they do not have to worry about mocking HttpContextBase and the details, they simply have to mock your HttpContextBaseWrapper class.

Edit:

I'd also recommend you to inject your HttpRequestContext as well, but if that's not possible then you can stub the RequestContext like so in the FakeHttpContext method:

var requestContext = MockRepository.GenerateStub<RequestContext>();
request.RequestContext = requestContext;

نصائح أخرى

Why don't you make an abstraction class which contains calls to the HttpContext base?

Then you can do something like this:

public class MyClass
{
   private readonly IHttpContext _httpContext;
   MyClass(IHttpContext httpContext)
   {
       _httpContext = httpContext;
   }

   public void Blaat()
   {
        _httpContext.DoYourThingsWithTheHttpContext();
    }
}

Assuming you are using dependency injection, otherwise look at the Fakes and Stubs framework from Microsoft.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top