使用IoC进行MVC 2验证属性单元测试

时间:2010-09-01 10:02:29

标签: unit-testing model-view-controller validation asp.net-mvc-2 castle-windsor

我目前正在为ASP.NET MVC 2控制器编写一些单元测试,并且在MVC 2.0验证属性方面存在一些问题。有问题的验证属性使用存储库来检查当前数据源中是否存在重复的名称,并且我想在单元测试期间用假的存储库替换此存储库。我正在使用Castle Windsor,根据this article,它允许我在运行时替换存储库,但我不确定如何在单元测试期间执行此操作。

大部分测试代码是:

[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触发并运行以下代码时,它会导致异常,因为存储库为null:

[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容器的目的。解决这个问题的最佳方法是,找到一种以某种方式模拟验证属性的方法,还是有一种方法可以在单元测试运行时注入假存储库?任何帮助/建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

我认为最好的办法是为您的单元测试创​​建一个假的DataAnnotationsModelValidator,它将在测试期间注入您的假存储库。您应该能够使其变得相当简单,以便限制它导致单元测试出现任何问题的可能性。

相关问题