1

我目前正在爲ASP.NET MVC 2控制器編寫一些單元測試,並且有一些MVC 2.0驗證屬性的問題。問題中的驗證屬性使用一個存儲庫來檢查當前數據源中是否存在重複的名稱,並且我希望在我的單元測試期間使用假的替換該存儲庫。我正在使用Castle Windsor,按照this article,它允許我在運行時替換存儲庫,但不知道在單元測試期間如何做到這一點。MVC 2驗證屬性使用IoC進行單元測試

堆積測試代碼的是這樣的:

[TestMethod] 
    public void TestSaveDuplicateTitleNameReturnsValidationErrorView() 
    { 
     //Arrange 
     var titleRepository = new FakeTitleRepository(); 
     var controller = new TitleController(titleRepository);    

     var selectedTitle = new Title(); 
     selectedTitle.Name = "Fru"; 

     //Act 
     var actual = controller.Save(selectedTitle); 

來自控制器的代碼示例是如下:

public ActionResult Save(Title SelectedTitle) 
    { 
     if (TryValidateModel(SelectedTitle)) 
     { 
      TitleRepository.Add(SelectedTitle); 
      TitleRepository.Save(); 

在測試期間在控制器本身正在使用的存儲庫是我的假一個我已經通過,但是當TryValidateModel觸發並且下面的代碼運行時,它會導致一個異常,因爲存儲庫爲空:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 
public class ValidTitleNameAttribute : ValidationAttribute 
{ 
    public ITitleRepository Repository { get; set; } 

    public override bool IsValid(object value) 
    { 
     bool isValid = true; 

     PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value); 
     object name = properties.Find("Name", true).GetValue(value); 

     if (name == null) 
     { 
      return isValid = false; 
     } 

     var titles = Repository.GetAllTitles(); 

很明顯,在存儲庫屬性中,我可以設置一個默認實例來引用一個具體的存儲庫,這樣可以防止測試期間的異常,但這會破壞使用IoC容器的目的。什麼是解決這個問題的最好方法,是以某種方式找到一種方法來模擬驗證屬性,或者在單元測試運行時Windsor是否可以注入僞造的存儲庫?任何幫助/建議將不勝感激。

+0

控制器應該有一個貪婪的構造函數,它使用它使用的存儲庫的接口,然後在測試方法中添加僞造的存儲庫。您可以將界面的實例化爲di,以保持關注點的分離。 – Joakim 2010-09-01 11:42:45

回答

1

我認爲最好的做法是爲您的單元測試創​​建一個假的DataAnnotationsModelValidator,它將在測試期間注入虛假的存儲庫。你應該能夠做到這一點非常簡單,以便限制它導致單元測試出現問題的機率。