首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >基于MVC验证的单元测试

基于MVC验证的单元测试
EN

Stack Overflow用户
提问于 2009-08-13 02:20:49
回答 11查看 26.1K关注 0票数 78

当我在MVC2Preview1中使用DataAnnotation验证时,如何测试我的控制器操作在验证实体时是否在ModelState中放置了正确的错误?

一些代码来说明。首先,动作:

代码语言:javascript
复制
    [HttpPost]
    public ActionResult Index(BlogPost b)
    {
        if(ModelState.IsValid)
        {
            _blogService.Insert(b);
            return(View("Success", b));
        }
        return View(b);
    }

这是一个失败的单元测试,我认为它应该通过,但没有通过(使用MbUnit & Moq):

代码语言:javascript
复制
[Test]
public void When_processing_invalid_post_HomeControllerModelState_should_have_at_least_one_error()
{
    // arrange
    var mockRepository = new Mock<IBlogPostSVC>();
    var homeController = new HomeController(mockRepository.Object);

    // act
    var p = new BlogPost { Title = "test" };            // date and content should be required
    homeController.Index(p);

    // assert
    Assert.IsTrue(!homeController.ModelState.IsValid);
}

我想除了这个问题之外,我是否应该测试验证,我应该以这种方式测试它吗?

EN

回答 11

Stack Overflow用户

回答已采纳

发布于 2009-08-13 07:32:09

您也可以将BlogPost参数声明为FormCollection,而不是传入actions。然后,您可以自己创建BlogPost并调用UpdateModel(model, formCollection.ToValueProvider());

这将触发对FormCollection中任何字段的验证。

代码语言:javascript
复制
    [HttpPost]
    public ActionResult Index(FormCollection form)
    {
        var b = new BlogPost();
        TryUpdateModel(model, form.ToValueProvider());

        if (ModelState.IsValid)
        {
            _blogService.Insert(b);
            return (View("Success", b));
        }
        return View(b);
    }

只需确保您的测试为视图表单中您希望保留为空的每个字段添加一个空值。

我发现这样做,以几行额外的代码为代价,使我的单元测试类似于代码在运行时被调用的方式,从而使它们更有价值。您还可以测试当有人在绑定到int属性的控件中输入"abc“时会发生什么。

票数 -4
EN

Stack Overflow用户

发布于 2010-07-28 21:08:09

我也遇到了同样的问题,在阅读了Paul的回答和评论后,我寻找了一种手动验证视图模型的方法。

我找到了this tutorial,它解释了如何手动验证使用DataAnnotations的ViewModel。关键代码片段在文章的末尾。

我稍微修改了一下代码--在本教程中省略了TryValidateObject的第四个参数(validateAllProperties)。为了验证所有的注解,应该将其设置为true。

此外,我将代码重构为一个泛型方法,以使ViewModel验证的测试变得简单:

代码语言:javascript
复制
    public static void ValidateViewModel<TViewModel, TController>(this TController controller, TViewModel viewModelToValidate) 
        where TController : ApiController
    {
        var validationContext = new ValidationContext(viewModelToValidate, null, null);
        var validationResults = new List<ValidationResult>();
        Validator.TryValidateObject(viewModelToValidate, validationContext, validationResults, true);
        foreach (var validationResult in validationResults)
        {
            controller.ModelState.AddModelError(validationResult.MemberNames.FirstOrDefault() ?? string.Empty, validationResult.ErrorMessage);
        }
    }

到目前为止,这对我们来说工作得很好。

票数 90
EN

Stack Overflow用户

发布于 2009-08-13 03:58:12

当您在测试中调用homeController.Index方法时,您没有使用任何触发验证的MVC框架,因此ModelState.IsValid始终为真。在我们的代码中,我们直接在控制器中调用助手验证方法,而不是使用环境验证。我没有太多使用DataAnnotations (我们使用NHibernate.Validators)的经验,也许其他人可以提供如何在你的控制器中调用Validate的指导。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1269713

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档