我正在尝试在MVC中的控制器上运行一个简单的测试。此控制器使用xVal和DataAnnotations验证输入。当我运行测试时(使用NUnit通过Resharper,NUnit独立或TestDriven.Net),它会使跑步者崩溃而没有正确的错误消息。在事件日志中,它只有一个相当通用的.NET Runtime 2.0错误报告消息,说明跑步者是一个错误的应用程序。
错误是由对ModelState.IsValid的调用引起的(我知道这是因为当我把它拿出来时运行正常)。此外,崩溃仅在我正常运行测试时发生。当我在调试模式下运行测试时,它工作正常。
当我删除对xVal的引用并使用ModelState.AddModelError在modelstate上设置错误时,它不会崩溃。
以下是被测控制器和测试类。你能在这看到什么问题吗?
受测试控制器
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,但至少这是一种解决方法。
答案 0 :(得分:0)
ModelState.IsValid不是由控制器设置的,它由模型绑定框架设置。模型绑定是仅在处理传入的HTTP请求时触发框架。当您像上面那样明确地调用控制器操作时,模型绑定不会发生,因此整个ModelState处于不确定状态。你有几个方法
模仿测试中的整个模型绑定内容,如此问题所示 - How can I test ModelState?
您可以在控制器操作中使用TryUpdateModel方法,如此问题所示 - Unit tests on MVC validation
编写单独的单元测试,以测试模型的基于属性的验证。为此,您需要更改基于属性验证的方法。阅读本文了解详情 - http://jesschadwick.blogspot.com/2009/04/cleaner-validation-with-aspnet-mvc.html