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,它将在测试期间注入虚假的存储库。你应该能够做到这一点非常简单,以便限制它导致单元测试出现问题的几率。