为什么ModelState.IsValid总是返回true?

Tan*_*jir 3 c# unit-testing asp.net-core-mvc asp.net-core

我必须对我BlogControllerCreatePost动作方法进行单元测试.我传递SavePostViewModel,而不象某些字段Author,SubjectPostdate所需要字段来测试CreatePost行动方法应该返回"无效的输入"这是在(!ModelState.IsValid)逻辑.但即使我传递一个null对象,它总是返回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; }
}
Run Code Online (Sandbox Code Playgroud)

我的控制器操作方法:

[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);
}
Run Code Online (Sandbox Code Playgroud)

我的测试方法:

[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);
}
Run Code Online (Sandbox Code Playgroud)

Nko*_*osi 5

在排列测试时,您必须手动更新控制器上的模型状态.这通常由框架在运行时完成,但由于这是一个独立的单元测试,因此您必须自己完成.

[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);    
}
Run Code Online (Sandbox Code Playgroud)