views:

111

answers:

0

I am trying to run a simple test on a controller in MVC. This controller validates the input using xVal and DataAnnotations. When I run the test (using NUnit via Resharper, NUnit standalone or TestDriven.Net) it crashes the runner with no decent error message. In the event logs it just has a fairly generic .NET Runtime 2.0 Error Reporting message saying that the runner was a Faulting application.

The error is caused by a call to ModelState.IsValid (I know this because when I take it out it runs fine). Also, the crash only occurs when I run the test normally. When I run the test in debug mode it works fine.

When I remove the references to xVal and set an error on the modelstate using ModelState.AddModelError, it doesn't crash.

Below is the controller under test and the test class. Can you see anything amiss here?

Controller Under Test

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);
        }
    }
}

Test Class

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);
        }
    }
}

Versions - ASP.Net MVC - 2.0.0.0, NUnit - 2.5.3.9345, xVal - 1.0.0.0

Update When I use the following statement instead (which is what ModelState.IsValid is doing under the covers) the crash does not occur...

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

I'd still prefer to use ModelState.IsValid, but at least this is a workaround.