2013-12-13 54 views
9

我試圖在我的MVC應用程序上運行一些測試,但我一直在經歷一個讓它工作的麻煩世界。我會盡量得到正確的一點是:如何嘲笑或僞造HttpApplication/HttpContext進行測試

我使用RhinoMocks嘗試這樣的事:

設置:

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; 

這裏的FakeHttpContext()方法:

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; 
} 

我真的需要訪問HttpContextBase.Request.AppRelativeCurrentExecutionFilePath,但它總是以null的形式返回。 HttpContext.Current.Request.RequestContext也是如此。

有人可以幫我嗎?可以肯定的是,我現在絕望了。

+0

你不要告訴問題是什麼?你有錯誤(哪一個?)?據我所見,特定的設置'安裝程序(c => c.Request。AppRelativeCurrentExecutionFilePath)'應該可以工作,因爲'Request'是一個'virtual'屬性'AppRelativeCurrentExecutionFilePath'的'virtual'屬性。你說'_mockContext.SetupAllProperties();'的原因是什麼?您還希望設置其他*屬性? –

+0

@JeppeStigNielsen我更新了我現在使用的問題。我仍然無法工作。 – Kehlan

回答

1

首先,請儘量避免使用HttpContext.Current,因爲使用靜態方法會使您現在發現的測試變得更加困難。如果您正在使用依賴注入框架,請將HttpContextBase注入到構造函數中。

爲您的實際問題,在FakeHttpContext()試圖改變

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

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

,然後在您的測試,你可以做這樣的事情:

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

我不認爲在HttpContext上進行部分模擬是非常有用的,因爲您將測試fra代替作業(即測試框架根據HttpContext中的值Y和Z返回正確值X)

另一種方法是創建一個圍繞HttpContextBase的包裝類,它將返回計算值。例如。 HttpContextBaseWrapper.AppRelativeCurrentExecutionFilePath(),HttpContextBaseWrapper.RequestIpAddress()。這將使得測試所有其他類更加簡單,因爲它們不必擔心模擬HttpContextBase和細節,而只需模擬HttpContextBaseWrapper類。

編輯:

我也建議你注入你的HttpRequestContext爲好,但如果這是不可能的,那麼你可以存根的RequestContext像這樣在FakeHttpContext方法:

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

我真的很感激這個答案。我編輯了OP,因爲我遇到了另一個問題。我還需要模擬'HttpContext.Current.Request.RequestContext'。你有什麼機會幫助我呢? – Kehlan

+0

我已更新我的答案,以允許您存根RequestContext。 –

+0

我不太清楚'HttpRequestContext'是什麼。我假設你的意思是'RequestContext'。再次感謝!我會試試看看它是如何發展的。 – Kehlan

1

爲什麼不製作一個包含對HttpContext庫的調用的抽象類?

然後,你可以做這樣的事情:

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

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

假設你正在使用依賴注入,否則看微軟的假動作和存根框架。