2009-08-11 47 views
19

首先的方法,我知道這個問題是危險地接近: How to MapPath in a unit test in C#C#單元測試:測試使用MapPath的

我希望但是,它有不同的解決方案。我的問題如下:

在我的代碼我有一個對象,需要驗證。我正在爲每個驗證方法創建單元測試,以確保它正確驗證。我正在創建模擬數據並將其加載到對象中,然後驗證它。問題在於,在驗證中,當發生錯誤時,會分配錯誤代碼。此錯誤代碼用於使用Server.MapPath從xml文件收集關於錯誤的信息。但是,在嘗試獲取xml文件時,會拋出異常,表示無法找到該文件。

由於MapPath在我的驗證代碼中,而不是我的單元測試,我該如何讓我的單元測試識別路徑?這個問題有意義嗎?

錯誤行(在我的驗證代碼不我的單元測試):

XDocument xdoc = XDocument.Load(HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml")); 

簡化:單元測試在我的程序調用使用Server.Mappath然後失敗調用的方法。

回答

15

我會將「文件名提供者」抽象爲一個只返回一個位置的類,然後你可以更容易地嘲笑它。

public class PathProvider 
{ 
    public virtual string GetPath() 
    { 
     return HttpContext.Current.Server.MapPath("App_Data/ErrorCodes.xml"); 
    } 
} 

然後,您既可以直接使用的PathProvider類...

PathProvider pathProvider = new PathProvider(); 
XDocument xdoc = XDocument.Load(pathProvider.GetPath()); 

或模擬它在你的檢查:

PathProvider pathProvider = new MockPathProvider(); // using a mocking framework 
XDocument xdoc = XDocument.Load(pathProvider.GetPath()); 
+2

GetPath()應該可能是虛擬的。 – dahlbyk 2009-08-11 17:31:56

+0

@Dan HttpContext.Current。當我們從TestProject運行時返回null。任何方式來避免這種情況? – 2016-05-30 06:59:43

+0

@JibinMathew是的,不要使用'HttpContext.Current'。我知道這聽起來很滑稽,但確實如此。通常,不要模擬你不擁有的類,但是你可以爲'HttpContextBase'編寫一個包裝類來實現你想要的功能。 – 2016-05-31 11:50:37

1

嘗試使用Rhino Mocks或替代模擬框架來模擬httpContext(或其他相關對象) 或者您可以編寫自己的模擬對象。 或者編寫一個MapPathWrapper類,從您的真實環境的MapPathWrapperBase類繼承,然後在您的單元測試中創建一個MockMapPathWrapper對象。

應該有很多嘲笑SO的例子。

這裏有一個我問:

How to use Rhino Mocks to Mock an HttpContext.Application

UPDATE 我只有經驗與Asp.Net MVC這樣做,用的WebForms我imagein這將是因爲缺乏了不少難度的HttpContextBase類。

1

我會提取接受你的依賴方法作爲參數:

public void Validate(HttpContext context) 
{ 
    ValidatePath(context.Server.MapPath("App_Data/ErrorCodes.xml")); 
} 

public void ValidatePath(string path) 
{ 
    XDocument xdoc = XDocument.Load(path); 
    ValidateDocument(xdoc); 
} 

public void ValidateDocument(XDocument xdoc) 
{ 
    // Original code 
} 

然後您可以獨立測試各種方法。例如,測試ValidatePath()如何處理丟失的文件。

11

經過一些嚴格的谷歌搜索和一位同事的幫助之後,我們想出了一個簡單的解決方案。淨

以上訪問驗證過程的單元測試,我說:

[TestMethod()] 
[HostType("ASP.NET")] 
[UrlToTest("http://localhost:###/upload_file.aspx")] 
[AspNetDevelopmentServerHost("Path To Web Application", "Path To Web Root")] 

這完美的作品。基本上,當測試被調用時,它會在頁面加載中加載具有指定單元測試的URL。由於它是一個現在正在調用單元測試的網站,因此驗證將有權訪問Server.MapPath。這種解決方案可能不適用於所有人,但它對此非常完美。感謝你的貢獻。

+1

像這樣的集成測試對確保所有組件一起工作確實很有用,但還有其他方案(如丟失的文件),此解決方案無法處理。產生測試Web應用程序也是一項相當昂貴的操作,如果您經常運行測試,這可能會加起來。 – dahlbyk 2009-08-11 21:13:12

+0

同意,雖然這種解決方案有一些優點,它可以提供有用的信息,但它不是單字測試的單元測試,它缺乏實際單元測試的最大好處。 – kai 2016-04-03 15:21:24

+0

這是一個偉大的時間保護程序! – Luther 2016-08-12 03:10:22