【问题标题】:How do I test an ASP.NET MVC2 post action with validation when using MvcContrib TestHelper?使用 MvcContrib TestHelper 时,如何通过验证测试 ASP.NET MVC2 发布操作?
【发布时间】:2010-10-12 22:39:50
【问题描述】:

我正在尝试为将视图模型作为其唯一参数的 ASP.NET MVC 2 发布操作编写单元测试。视图模型装饰有验证属性,例如 [Required]。我想测试两个场景。第一种情况是传入一组有效数据(即所有必需的属性都有值)并返回到列表页面的重定向。第二种情况涉及传入无效数据(例如,当一个或多个必需属性未设置时)。在这种情况下,将返回相同的视图并显示错误消息。

动作签名如下:

[HttpPost]
public virtual ActionResult Create(NewsViewModel model)

NewsViewModel 类如下:

public class NewsViewModel
{

    public Guid Id { get; set; }

    public DateTime? PublishStartDate { get; set; }

    public DateTime? PublishEndDate { get; set; }

    [Required]
    [StringLength(1000, 
        ErrorMessage = "Title must be less than 1000 characters.")]
    [HtmlProperties(Size = 100, MaxLength = 1000)]
    public string Title { get; set; }

    [Required]
    public string Content { get; set; }

    [DisplayName("Published")]
    [Required]
    public bool IsPublished { get; set; }

    [Required]
    public string Category { get; set; }

    public DateTime PublishedDateTime { get; set; }
}

我对第一个场景的单元测试如下:

[Test]
public void Create_Post()
{
    DateTime now = DateTime.Now;
    Guid id = Guid.NewGuid();

    // Act
    NewsViewModel viewModel = new NewsViewModel()
    {
        Id = id,
        Title = "Test News",
        Content = "this is the content",
        Category = "General",
        PublishedDateTime = now,
        PublishEndDate = now.Add(new TimeSpan(1, 0, 0)),
        PublishStartDate = now.Subtract(new TimeSpan(1, 0, 0))
    };

    ActionResult result = _controller.Create(viewModel);

    // Assert
    result.AssertActionRedirect();
}

控制器是使用 MvcContrib TestControllerBuilder 在测试设置中创建的:

private IWebDataService _webDataServiceFake;
private TestControllerBuilder _builder;
private PortalNewsController _controller;

[SetUp]
public void Setup()
{
    _webDataServiceFake = new WebDataService(new EntityDataServiceFake());
    _controller = new PortalNewsController(_webDataServiceFake);
    _builder = new TestControllerBuilder();
    _builder.InitializeController(_controller);
}

此测试按预期通过,返回一个重定向到列表页面的操作。我想创建一个它的克隆,其中许多必需的属性为空或空。在这种情况下,测试应该返回视图渲染操作而不是重定向。我的尝试如下:

[Test]
public void Create_PostInvalid()
{
    DateTime now = DateTime.Now;
    Guid id = Guid.NewGuid();

    // Act
    NewsViewModel viewModel = new NewsViewModel()
    {
        Id = id,
        Title = null,
        PublishedDateTime = now,
        PublishEndDate = now.Add(new TimeSpan(1, 0, 0)),
        PublishStartDate = now.Subtract(new TimeSpan(1, 0, 0)),
        Content = null,
        Category = ""
    };

    ActionResult result = _controller.Create(viewModel);

    // Assert
    result.AssertViewRendered();
}

即使我为 Content 属性传递了一个 null 并为 Category 属性传递了一个空字符串,但单元测试还是失败了,因为当我调用 Create 操作时,ViewState 表明模型是有效的。

我假设我调用操作时没有调用验证代码,因为我直接调用它我并不感到惊讶。那么,在调用 action 方法之前,如何编写一个单元测试来在视图模型上执行所有预期的验证呢?

我正在使用:ASP.NET MVC2、NUnit 2.5.7 和 MvcContrib 2.0.96.0。

感谢您的帮助。 格伦。

【问题讨论】:

  • 阅读 Brad 提供的链接后,我发现诀窍是添加“_controller.ModelState.AddModelError("*", "Invalid model state");"就在调用 Create 操作之前。这向控制器表明发生了验证错误,因此根据需要通过代码采用无效路径。谢谢布拉德。

标签: c# asp.net asp.net-mvc-2 nunit mvccontrib


【解决方案1】:

我建议您阅读 Brad Wilson 关于此主题的 excellent blog post。基本上,它使用反射来确保将正确的属性应用于您的模型并依赖框架来完成其工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-05
    • 1970-01-01
    相关资源
    最近更新 更多