【问题标题】:xVal Causing NUnit to Crash when checking ModelState.IsValidxVal 在检查 ModelState.IsValid 时导致 NUnit 崩溃
【发布时间】:2011-01-18 07:26:04
【问题描述】:

我正在尝试在 MVC 中的控制器上运行一个简单的测试。此控制器使用 xVal 和 DataAnnotations 验证输入。当我运行测试(通过 Resharper、NUnit 独立或 TestDriven.Net 使用 NUnit)时,它会在没有像样的错误消息的情况下使运行器崩溃。在事件日志中,它只有一条相当通用的 .NET Runtime 2.0 错误报告消息,说明运行器是一个错误应用程序。

错误是由调用 ModelState.IsValid 引起的(我知道这一点是因为当我把它拿出来时它运行良好)。此外,只有在我正常运行测试时才会发生崩溃。当我在调试模式下运行测试时,它工作正常。

当我删除对 xVal 的引用并使用 ModelState.AddModelError 在模型状态上设置错误时,它不会崩溃。

下面是被测控制器和测试类。你能看出这里有什么不对吗?

被测控制器

using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using xVal.ServerSide;

namespace TestModelState.Controllers
{
    public class ThingController : Controller
    {
        [HttpPost]
        public ActionResult Create(Thing thing)
        {
            try
            {
                var errors = DataAnnotationsValidationRunner.GetErrors(thing);
                if (errors.Any())
                {
                    throw new RulesException(errors);
                }
            }
            catch (RulesException ex)
            {
                ex.AddModelStateErrors(ModelState, "thing");
            }
            if (ModelState.IsValid)
            {
                // Do some save stuff here
                return RedirectToAction("Index");
            }
            else
            {
                return View();
            }
        }
    }

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

    internal static class DataAnnotationsValidationRunner
    {
        public static IEnumerable<ErrorInfo> GetErrors(object instance)
        {
            return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>()
                   from attribute in prop.Attributes.OfType<ValidationAttribute>()
                   where !attribute.IsValid(prop.GetValue(instance))
                   select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);
        }
    }
}

测试类

using System.Web.Mvc;
using NUnit.Framework;
using TestModelState.Controllers;

namespace TestModelState.Tests
{
    [TestFixture]
    public class ThingControllerTests
    {
        [Test]
        public void Create_InvalidThing_SetsModelState()
        {
            // Arrange
            var thingController = new ThingController();
            var thing = new Thing();

            // Act
            var result = thingController.Create(thing);

            // Assert
            var viewResult = (ViewResult)result;
            Assert.IsFalse(viewResult.ViewData.ModelState.IsValid);
        }
    }
}

版本 - ASP.Net MVC - 2.0.0.0,NUnit - 2.5.3.9345,xVal - 1.0.0.0

更新 当我改用以下语句时(这就是 ModelState.IsValid 在幕后所做的),不会发生崩溃...

var modelStateIsValid = ModelState.Values.All(ms => ms.Errors.Count == 0);

我仍然更喜欢使用 ModelState.IsValid,但至少这是一种解决方法。

【问题讨论】:

  • 我也一样。这很奇怪!。

标签: asp.net-mvc unit-testing validation nunit xval


【解决方案1】:

ModelState.IsValid 不是由控制器设置的,它是由模型绑定框架设置的。模型绑定是框架仅在处理传入的 HTTP 请求时触发。当您像上面那样显式调用控制器操作时,模型绑定不会发生,因此整个 ModelState 处于不确定状态。你有几种方法

  1. 在你的测试中模仿整个模型绑定的东西,如这个 SO 问题 - How can I test ModelState?

  2. 您可以在控制器操作中使用 TryUpdateModel 方法,如此 SO 问题中给出的 - Unit tests on MVC validation

  3. 编写单独的单元测试来测试模型的基于属性的验证。为此,您需要改变您对基于属性的验证的方法。阅读本文了解详情 - http://jesschadwick.blogspot.com/2009/04/cleaner-validation-with-aspnet-mvc.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2018-01-23
    • 2020-12-02
    • 2013-11-11
    • 2011-01-24
    • 2015-02-23
    • 2011-04-23
    相关资源
    最近更新 更多