2013-12-07 218 views
1

我想弄清楚爲MVC應用程序構建單元測試的最佳方法。我創建了一個簡單的模型和接口,供控制器構造函數使用,以便測試框架(Nsubstitute)可以傳遞存儲庫的模擬版本。正如預期的那樣,此測試通過。單元測試MVC控制器

我現在的問題是我想更進一步,在IHomeRepository的「真實」實例中測試文件I/O操作。這個實現應該從App_Data目錄中的一個文件中讀取一個值。

我試過在沒有傳遞IHomeRepsotory的模擬版本的情況下構建一個測試,但是當我運行我的測試時,HttpContext.Current爲null。

我需要模擬HttpContext嗎?我是否以正確的方式去解決這個問題?

//The model 
public class VersionModel 
{ 
    public String BuildNumber { get; set; } 
} 



//Interface defining the repository 
public interface IHomeRepository 
{ 
    VersionModel Version { get; } 
} 


//define the controller so the unit testing framework can pass in a mocked reposiotry. The default constructor creates a real repository 
public class HomeController : Controller 
{ 

    public IHomeRepository HomeRepository; 

    public HomeController() 
    { 
     HomeRepository = new HomeRepoRepository(); 
    } 

    public HomeController(IHomeRepository homeRepository) 
    { 
     HomeRepository = homeRepository; 
    } 
. 
. 
. 

} 


class HomeRepoRepository : IHomeRepository 
{ 
    private VersionModel _version; 

    VersionModel IHomeRepository.Version 
    { 
     get 
     { 
      if (_version == null) 
      { 
       var absoluteFileLocation = HttpContext.Current.Server.MapPath("~/App_Data/repo.txt"); 
       if (absoluteFileLocation != null) 
       {   
        _version = new VersionModel() //read the values from file (not shown here) 
        { 
         BuildNumber = "value from file", 
        }; 
       } 
       else 
       { 
        throw new Exception("path is null"); 
       } 
      } 
      return _version; 
     } 
    } 
} 



[Fact] 
public void Version() 
{ 
    // Arrange 
    var repo = Substitute.For<IHomeRepository>(); //using Nsubstitute, but could be any mock framework 
    repo.Version.Returns(new VersionModel 
    { 
     BuildNumber = "1.2.3.4", 
    }); 

    HomeController controller = new HomeController(repo); //pass in the mocked repository 

    // Act 
    ViewResult result = controller.Version() as ViewResult; 
    var m = (VersionModel)result.Model; 

    // Assert 
    Assert.True(!string.IsNullOrEmpty(m.Changeset)); 
} 

回答

1

我相信你要測試連接到真實數據庫的IHomeRepository的實例。在這種情況下,您需要一個App.config file, which specify the connection string。這不是單元測試,而是集成測試。在HttpContext爲空的情況下,您仍然在can fake the HttpContext中,從數據庫中檢索真實數據。另請參閱here

+0

我最初的問題是正確讀取文件。我最好把代碼放在一個帶有文件路徑參數的單獨的類中,然後單元測試那個類? – WhiskerBiscuit

+0

這取決於你如何閱讀文件。例如,當你讀取文件時你有什麼邏輯。如果這不是微不足道的話,那麼正是你所說的。將代碼放在一個單獨的類中,並將其作爲集成測試進行操作。所以你不必擔心HttpContext。如果您的文件足夠簡單,我不會擔心將它放入單獨的課程並進行測試。在這種情況下,你的單元測試就足夠了。 – Spock

+0

你認爲這種方法會更好嗎? http://stackoverflow.com/questions/8740498/how-to-unit-test-code-that-uses-hostingenvironment-mappath – WhiskerBiscuit