2010-02-18 21 views
2

我想在MVC中的控制器上運行一個簡單的測試。該控制器使用xVal和DataAnnotations驗證輸入。當我運行測試時(使用NUnit通過Resharper,NUnit standalone或TestDriven.Net),它沒有像樣的錯誤信息而讓跑步者崩潰。在事件日誌中,它只是具有一個相當通用的.NET Runtime 2.0錯誤報告消息,說明runner是一個Faulting應用程序。xVal導致NUnit在檢查ModelState.IsValid時崩潰

該錯誤是由對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

我也一樣。這很古怪 !!。 – 2010-03-08 09:45:43

回答

0

ModelState.IsValid未由控制器設置,它由模型綁定框架設置。只有在處理傳入的HTTP請求時纔會觸發模型綁定。當你像上面那樣明確地調用控制器動作時,模型綁定不會發生,因此整個ModelState處於不確定狀態。你有幾個方法

  1. 模仿整個模型在這太問題給出你的測試結合的東西 - How can I test ModelState?

  2. 您可以使用TryUpdateModel方法在你的控制器行動,在這太問題給出 - Unit tests on MVC validation

  3. 編寫單獨的單元測試,測試模型的基於屬性的驗證。爲此,您需要更改您的方法,以實現基於屬性的驗證。閱讀這篇文章的細節 - http://jesschadwick.blogspot.com/2009/04/cleaner-validation-with-aspnet-mvc.html