Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ModelState.IsValid always return true?

I have to unit test my BlogController's CreatePost action method. I am passing SavePostViewModel without some fields like Author, Subject, and Postdate which are required field to test CreatePost action method should returns "Invalid Input" which is in (!ModelState.IsValid) logic. But it's always return true even when I am passing a null object.

My View Model:

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; }
}

My Controller Action Method:

[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);
}

My Test Method:

[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);
}
like image 890
Tanjir Avatar asked Apr 12 '18 03:04

Tanjir


1 Answers

You will have to update the model state on the controller manually when arranging the test. This is normally done by the framework at runtime but since this is an isolated unit test you will have to do it yourself.

[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);    
}
like image 84
Nkosi Avatar answered Oct 02 '22 22:10

Nkosi