2016-07-19 26 views
2

我正在ASP.net MVC 5應用程序中工作。我想單元測試我的控制器動作,看起來像這樣如何避免HttpContext.Server.MapPath用於單元測試目的

public ActionResult Search() 
{ 
    var vm = SetupSearchViewModel(); 

    return View(vm); 
} 

所有的辛勤工作是由SetupSearchViewModel()方法,它本身就是一個協調器調用許多不同的其他方法,其中之一就是這個

完成
private string ExtractJsonFile(string filename) 
{ 
    var filePath = HttpContext.Server.MapPath(filename); 
    var json = System.IO.File.ReadAllText(filePath); 
    return json; 
} 

我打算在這個特別的動作做很多單元測試,但我開始有一個非常簡單的單元測試,檢查時返回的正確類型的ActionResult的

[Test] 
public void Search_Get_ReturnsViewResult() 
{ 
    // arrange 
    var performanceController = PerformanceControllerInstance; 
    // act 
    var result = performanceController.Search(); 
    //assert 
    Assert.IsNotNull(result as ViewResult); 
} 

由於ExtractJsonFile方法的原因,測試失敗。它使用HttpContext,那就是null。我正在使用Rhino Mocks來模擬各種課程。

單元測試的最佳方式是什麼? Darin在this thread建議我們避免HttpContext.Current,如果我們想要我們的代碼單元測試。

通過我試過的方式嘲諷的HttpContext,並使其不爲空,但隨後的Servernull,我可以繼續和模擬太我想(我不知道怎麼還沒有),但有沒有更好的辦法?如果需要進行重大重構,我沒有問題。

回答

4

HttpContext.Server.MapPath將需要在單元測試期間不存在的基礎虛擬目錄提供者。抽象出您可以模擬代碼進行測試的服務背後的路徑映射。

public interface IPathProvider { 
    string MapPath(string path); 
} 

在具體服務的實現中,您可以調用映射路徑和檢索文件。

public class ServerPathProvider: IPathProvider { 
    public string MapPath(string path) { 
     return HttpContext.Current.Server.MapPath(path); 
    } 
} 

你會注入抽象到控制器中或在需要的地方,並使用

public MyController : Controller { 

    public MyController(IPathProvider pathProvider) { 
     this.pathProvider = pathProvider; 
    } 

    //...other code removed for brevity 

    private string ExtractJsonFile(string filename) { 
     var filePath = pathProvider.MapPath(filename); 
     var json = System.IO.File.ReadAllText(filePath); 
     return json; 
    } 
} 

使用您選擇的模擬框架,那麼你可以嘲笑提供商

[Test] 
public void Search_Get_ReturnsViewResult() { 
    // arrange 
    IPathProvider mockedPathProvider = //...insert your mock/fake/stub here 
    var performanceController = PerformanceControllerInstance(mockedPathProvider); 
    // act 
    var result = performanceController.Search(); 
    //assert 
    Assert.IsNotNull(result as ViewResult); 
} 

,而不是連接到HttpContext

你甚至可以去furt她並將整個ExtractJsonFile(string filename)重構爲自己的服務,以避免與磁盤綁定。

public interface IJsonProvider { 
    string ExtractJsonFile(string filename); 
} 

此服務現在足夠靈活,可以根據需要從其他來源(如Web服務)獲取文件。

相關問題