【问题标题】:Controller Unit Testing with model validation带有模型验证的控制器单元测试
【发布时间】:2013-08-09 18:26:25
【问题描述】:

我开始学习 MVC4 中的单元测试。

这是我的控制器。

public class AccountController : Controller
{
    public ActionResult Register(User user)
    {
        if (ModelState.IsValid)
        {
            return View("RegistrationSuccessful");                
        }
        return View("Register");
    }
}

这就是测试。

public class AccountControllerTests
{
    [TestMethod]
    public void invalid_registration_details_should_show_registration_form_again()
    {
        var controller = new AccountController();
        var user = new User();
        user.Name = null;
        var result = controller.Register(user) as ViewResult;
        Assert.AreEqual("Register", result.ViewName);
    }
}

这就是模型。

public class User
{
    [Required]
    public string Name { get; set; }
}

当我调用 controller.Register(user) 时,我认为模型绑定器不会出现,因为我自己实例化控制器而不是通过框架。所以我认为 ModelState.IsValid 默认为真。

我该如何测试呢?如何在单元测试中触发模型验证?

【问题讨论】:

    标签: asp.net-mvc unit-testing


    【解决方案1】:

    您也可以通过以下方法来验证模型。在我的例子中,ProjectViewModel 是我的模型。在下面的场景中,我没有设置 Description 属性来验证验证是否有效。

    [TestMethod]
    [ExpectedException(typeof(ValidationException), "Please enter description.")]
    public void Create_Project_Empty_Description()
    {
        ProjectViewModel model = new ProjectViewModel
        {
            ProjectID = 3,
            Name = "Test Project",
            StartDate = DateTime.Now.Date,
            EndDate = DateTime.Now.AddMonths(-1),
            States = new List<ProjectStateViewModel> { new ProjectStateViewModel { StateName = "Pending" } }
        };
    
        ValidationContext contex = new ValidationContext(model);
        Validator.ValidateObject(model, contex);
    }
    

    【讨论】:

    【解决方案2】:

    由于控制器中除了检查 ModelState.IsValid==true 之外没有其他逻辑,我认为您可能只需要对模型进行单元测试。

    首先,您的模型。我会将其更改为如下所示:

    public class User : IValidatableObject
    {
        public string Name { get; set; }
        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            // I personally add all my validation here instead of adding [Required] to specific properties, this helps me know all of my validation is in this one place and add other complex validations if needed
            // This code here determines if ModelState.IsValid 
            var retVal = new List<ValidationResult>();
            if (string.IsNullOrEmpty(this.Name))
            {
                retVal.Add(new ValidationResult("Name is Empty", new List<string> { "Name" }));
            }
            return retVal;
        }
    }
    

    第二,单元测试。我会编写测试,我希望特定属性的特定错误消息。在此示例中,我给出了一个空值,并期待属性“名称”的错误消息“名称为空”:

        [TestMethod]
        public void NullOrEmptyName()
        {
            var model = new YourProject.Models.Account.User { Name= null };
            var validationContext = new ValidationContext(model);
            var validation = model.Validate(validationContext).ToList();
            Assert.AreEqual(validation.Count(x => x.ErrorMessage == "Name is empty" && x.MemberNames.Single() == "Name"), 1);
        }
    

    【讨论】:

      【解决方案3】:

      我不确定是否可以触发模型验证,但我知道如何测试它。

      试试这个代码:

          [TestClass]
          public class AccountControllerTests
          {
              [TestMethod]
              public void invalid_registration_details_should_show_registration_form_again()
              {
                  // arrange
                  var controller = new AccountController();
                  controller.ViewData.ModelState.AddModelError("Key", "ErrorMessage");
      
                  // act
                  var result = controller.Register(new User()) as ViewResult;
      
                  // assert
                  Assert.AreEqual("Register", result.ViewName);
              }
      
              [TestMethod]
              public void valid_registration_details_should_show_registration_successful_page()
              {
                  // arrange
                  var controller = new AccountController();
      
                  // act
                  var result = controller.Register(new User()) as ViewResult;
      
                  // assert
                  Assert.AreEqual("RegistrationSuccessful", result.ViewName);
              }
          }
      

      【讨论】:

        【解决方案4】:

        您可以通过调用以下测试来强制它验证您的模型来做到这一点。对于我的测试,我创建了一个 TestHelper 类,其中模拟了这个方法,并为特定条件添加了 ModelState.AddModelError()

        TryValidateModel(model);// will do the task
        

        您可能还需要为此模拟 ControllerContext

        【讨论】:

          猜你喜欢
          • 2017-08-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-30
          • 2016-07-25
          • 2019-07-11
          • 2016-06-08
          • 1970-01-01
          相关资源
          最近更新 更多