为什么ModelState.IsValid始终返回true?

5
我需要对我的BlogController中的CreatePost操作方法进行单元测试。我传递了SavePostViewModel,但没有传递一些必填字段,如AuthorSubjectPostdate,这些字段是测试CreatePost操作方法应该返回"Invalid Input"的必要条件,而这个条件在(!ModelState.IsValid)逻辑中。但即使我传递了一个空对象,它仍然总是返回true。
我的视图模型:
public class SavePostViewModel : ISavePostDto
{
    public SavePostViewModel()
    {
        PostDate = Helper.LocalDateToday;
        CategoryIds = new List<int>();
    }

    [DisplayName("Post ID")]
    public int? Id { get; set; }

    [DisplayName("Post Date")]
    [Required(ErrorMessage = "{0} is required")]
    public DateTime PostDate { get; set; }

    [DisplayName("Mata Title")]
    public string MetaTitle { get; set; }

    [DisplayName("Mata Keywords")]
    public string MetaKeywords { get; set; }

    [DisplayName("Mata Description")]
    public string MetaDescription { get; set; }

    [DisplayName("Author")]
    [Required(ErrorMessage = "{0} is required")]
    [StringLength(100, ErrorMessage = "{0} can be maximum of {1} characters")]
    public string Author { get; set; }

    [DisplayName("Subject")]
    [Required(ErrorMessage = "{0} is required")]
    [StringLength(100, ErrorMessage = "{0} can be maximum of {1} characters")]
    public string Subject { get; set; }

    [DisplayName("Short Description")]
    [Required(ErrorMessage = "{0} is required")]
    [StringLength(500, ErrorMessage = "{0} can be maximum of {1} characters")]
    public string ShortDesc { get; set; }

    [DisplayName("Content")]
    public string Content { get; set; }

    [DisplayName("Categories")]
    public List<int> CategoryIds { get; set; }

    [DisplayName("URL Key")]
    public string UrlKey { get; set; }

    public bool  IsPublished { get; set; }

    public string PhotoPath { get; set; }

    public string PhotoVersion { get; set; }
}

我的控制器操作方法:

[HttpPost] 
public async Task<IActionResult> CreatePost(SavePostViewModel model)
{
    if (!ModelState.IsValid)
    {
        ViewData[MESSAGE_KEY_ERROR] = "Invalid input";
        return View(model);
    }

    var result = await _blogService.CreatePostAsync(model);

    if (result.Status != TaskResult.StatusCodes.SUCCESS)
    {
        ViewData[MESSAGE_KEY_ERROR] = result.Message;
        return View(model);
    }

    TempData["PROMPT_PHOTO_UPLOAD"] = "TRUE";

    return Redirect("/Blog/EditPost/" + result.Post.Id);
}

我的测试方法:

[Test]  
public async Task HttpPost_CreatePost_When_Model_Is_Invalid_Returns_Error()
{
    // Arrange
    var expectedErrorMessage = "Invalid input";
    var model = new SavePostViewModel()
    {
        //Author = "Tamim Iqbal",
        Content = "New Content",
        IsPublished = true,
        //Subject = "New Subject",
        //PostDate = Helper.LocalDateToday,
    };

    // Act
    var result = await _blogController.CreatePost(model) as ViewResult;
    var actualErrorMessage = result.ViewData["ERROR_MESSAGE"];

    // Assert
    Assert.AreEqual(expectedErrorMessage, actualErrorMessage);
}

在编写测试时,由于这是一个独立的单元测试,因此通常情况下框架会在运行时自动更新控制器上的模型状态。但是,在这种情况下,您需要手动更新控制器上的模型状态。 - Nkosi
1个回答

7

在安排测试时,您将需要手动更新控制器上的模型状态。通常情况下,这是由框架在运行时完成的,但由于这是一项独立的单元测试,因此您必须自己完成。

[Test]  
public async Task HttpPost_CreatePost_When_Model_Is_Invalid_Returns_Error() {    
    // Arrange
    var expectedErrorMessage = "Invalid input";
    var model = new SavePostViewModel() {
        //Author = "Tamim Iqbal",
        Content = "New Content",
        IsPublished = true,
        //Subject = "New Subject",
        //PostDate = Helper.LocalDateToday,
    };
    //Adding model state to force it to be invalid
    _blogController.ModelState.AddModelError("", "invalid data");

    // Act
    var result = await _blogController.CreatePost(model) as ViewResult;
    var actualErrorMessage = result.ViewData["ERROR_MESSAGE"];

    // Assert
    Assert.AreEqual(expectedErrorMessage, actualErrorMessage);    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接