2012-05-14 53 views
1

我仍然試圖添加一些ASP.NET站點(而不是MVC)的單元測試。我需要測試的一種方法是使用HttpRequest Request對象,確切地說是Request.Path。我正在嘗試使用Visual Studio 2008內置的測試框架編寫測試。每當測試執行所述方法時,我收到System.Web.HttpExecption: Request is not Available in this context。我明白爲什麼它不可用(沒有正在運行的Web服務器並且沒有提供路徑),但我該如何繼續測試該方法?單元測試ASP.NET(而不是MVC) - 我如何過去「請求在此上下文中不可用」?

既然大家都喜歡看代碼,這裏是有問題的代碼:

protected string PageName 
{ 
    get 
    { 
     return Path.GetFileName(Request.Path).Substring(0, Path.GetFileName(Request.Path).Length - 5); 
    } 
} 

protected Change SetupApproval(string changeDescription) 
{ 
    Change change = Change.GetInstance(); 
    change.Description = changeDescription; 
    change.DateOfChange = DateTime.Now; 
    change.Page = PageName; 
    return change; 
} 

這裏的測試:通過微軟的文檔

[TestMethod] 
public void SetupApproval_SubmitChange_ValidateDescription() 
{ 
    var page = new DerivedFromInternalAppsBasePage_ForTestingOnly(); 
    var messageToTest = "This is a test description"; 
    var change = page.SetupApproval(messageToTest); 
    Assert.IsTrue(messageToTest == change.Description); 
} 

另外,我已經讀到這裏:http://msdn.microsoft.com/en-us/library/ms182526(v=vs.90).aspx 和嘗試使用[HostType("ASP.NET")],[UrlToTest(http://localhost:port/pathToAspxPage.aspx")][AspNetDevelopmentServer("C:\PathToDllAssembly", "NotSureParameter")]他們建議的屬性,但沒有運氣。 (正如你所看到的,我不確定我應該使用幾個參數。)。

最後,我想菲爾哈克的TestWebServer http://haacked.com/archive/2006/12/12/Using_WebServer.WebDev_For_Unit_Tests.aspx 並通過斯科特Hanselman的後http://www.hanselman.com/blog/NUnitUnitTestingOfASPNETPagesBaseClassesControlsAndOtherWidgetryUsingCassiniASPNETWebMatrixVisualStudioWebDeveloper.aspx 對於菲爾的服務器讀取,我不知道我會在ExtractResource方法使用的參數。

+1

「傳統的單元測試的智慧」(J/K)將建議取消從依賴該代碼並允許它從模擬對象傳入或管理。 –

回答

3

我一直在努力解決類似的問題,真正有用的是微軟研究院的Moles框架 - http://research.microsoft.com/en-us/projects/moles/。它允許你僞造BCL中的任何東西,包括HttpContext.Current。

+0

我認爲有更好的方法來解決這個問題(見下文)。在這種情況下,TypeMock Isolator也可以使用。 – dplante

0

使用HttpContext測試方法的關鍵是使用HttpContextBase。 HttpContextBase是一個抽象類,它可以輕鬆地進行嘲弄。不幸的是HttpContext沒有實現HttpContextBase,所以你需要使用HttpContextWrapper將真實的HttpContext包裝到HttpContextBase中。本文有一個很好和簡單的解釋:http://splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext

您的問題沒有說明示例代碼的位置。如果全部都在代碼隱藏中,那麼您將很難嘗試測試它。不要在代碼隱藏中使用邏輯,您應該查看Model-View-Presenter(MVP) -pattern。有MVP的框架,但它也很容易自己做。

在MVP展示器中包含所有的邏輯和頁面代碼隱藏僅實現了包含可綁定到UI的屬性的View-interface。所有的依賴關係都可以注入演示者,使其易於測試。

0

我同意@Alex Taylor(對不起,我不能評論):單元測試(非MVC)網絡應用程序的最佳方式是確保位不要依賴於整個環境在場;這就是爲什麼它被稱爲單元畢竟測試。所以,你可以替換PageName這個:

protected string PageName 
{ 
    get 
    { 
     return GetPageName(Request.Path); 
    } 
} 

protected static string GetPageName(string path) 
{ 
    return Path.GetFileNameWithoutExtension(path); 
} 

而與此你可以單元測試GetPageName,並確信頁面名稱按預期工作。

請記住,嘗試單元測試Request.Path是沒有意義的,因爲它具有應該實現的預期行爲(或「合同」)。如果你不確定什麼請求。路徑將在不同情況下返回,您應該檢查documentation而不是添加單元測試。

2

有一個非常類似的問題,其在書中"Working Effectively with Legacy Code"由邁克爾羽毛描述你所遇到的一個。特別是,重構被稱爲「適應參數」。

您的代碼的「問題」是它直接耦合到HttpRequest,特別是Request.Path。所以總體方法是你想從HttpRequest解耦你的代碼。

與上面提出的建議類似,下面是另一種方式來解決Michael Feather書中的想法。我沒有試過編譯這個,所以請原諒任何錯誤或語法錯誤。

 
public interface ParameterSource 
{ 
    public string Path {get; } 
} 

public class FakeParameterSource : ParameterSource 
{ 
    public string Value; 
    public string Path { get { return Value } } 
} 

public class RealParameterSource : ParameterSource 
{ 
    private HttpRequest request; 
    public RealParameterSource(HttpRequest aRequest) 
    { 
    request = aRequest; 
    } 
    public string Path { get { return request.Path } } 
} 

現在,這裏有你需要改變什麼重要組成部分(這裏是這樣做的一種方法):

 
// small rename 
protected string GetPageName(ParameterSource source) 
{ 
    return Path.GetFileName(source.Path).Substring(0, Path.GetFileName(source.Path).Length - 5); 
} 

注射以上發生在方法層面。你可以通過構造函數或屬性來完成。

你的測試代碼現在可能是這樣的:

 
protected Change SetupApproval(string changeDescription) 
{ 
    ParameterSource p = new FakeParameterSource { Value = "mypath" }; 
    Change change = Change.GetInstance(); 
    change.Description = changeDescription; 
    change.DateOfChange = DateTime.Now; 
    change.Page = GetPageName(p); // now uses the value in the parameter source 
    return change; 
} 

我希望你的想法和發現這很有

+0

感謝好的獎勵:) :) :) !!!!!!!!!! – dplante

相關問題