在Asp.Net MVC Web Api中测试Controller时,ModelState.IsValid始终为true

时间:2016-06-01 01:27:34

标签: c# testing asp.net-web-api modelstate

我尝试过这项工作并进行了许多google / stackoverflow搜索,但根本没有运气。

我有一个简单的模型:

public class MovieModel
{
    public string Id { get; set; }

    [Required]
    [StringLength(100)]
    public string Name { get; set; }
}

控制器中的方法:

// POST: api/Movies
public IHttpActionResult Post([FromBody]MovieModel movieModel)
{
    if (ModelState.IsValid)
    {
        //Code
    }
}

测试方法(是一种集成测试,但在单元测试中会发生同样的情况):

[TestMethod]
public void MoviesController_Post_Without_Name()
{
    // Arrange
    var model = new MovieModel();
    model.Name = "";

    // Act
    var result = controller.Post(model);

    // Assert
    Assert.IsInstanceOfType(result, typeof(InvalidModelStateResult));
    Assert.AreEqual(6, controller.Get().Count());
}

尽管模型显然无效,但它始终将IsValid属性评估为true。

到目前为止,我尝试了许多方法但没有成功。

4 个答案:

答案 0 :(得分:8)

感谢this网站,我找到了解决方案:

private void SimulateValidation(object model)
{
    // mimic the behaviour of the model binder which is responsible for Validating the Model
    var validationContext = new ValidationContext(model, null, null);
    var validationResults = new List<ValidationResult>();
    Validator.TryValidateObject(model, validationContext, validationResults, true);
    foreach (var validationResult in validationResults)
    {
        this.controller.ModelState.AddModelError(validationResult.MemberNames.First(), validationResult.ErrorMessage);
    }
}

在测试方法中包含一行,如下所示:

public void MoviesController_Post_Without_Name()
{
    // Arrange
    var model = new MovieModel();
    model.Name = "";

    // Act
    SimulateValidation(model);
    var result = controller.Post(model);

    // Assert
    Assert.IsInstanceOfType(result, typeof(InvalidModelStateResult));
    Assert.AreEqual(6, controller.Get().Count());
}

希望能帮到某个人,这样可以节省我一些时间在网上搜索。

答案 1 :(得分:7)

您的解决方案可能有效,但更好的方法是使用ApiController.Validate方法。

$('body').on('click', '.fc-day-number', function(event) {
   var target = event.target;
   var day = parseInt(target.innerHTML);
   var date = $(target).attr('data-date');
   var url = 'http://www.example.com/booking.php?booking_date=' + date;
   var win = window.open(url, '_blank');
   win.focus();
 })

答案 2 :(得分:0)

这对我有用:

public MyResultData Post([FromBody] MyQueryData queryData)
{
    if (!this.Request.Properties.ContainsKey("MS_HttpConfiguration")) 
    {
        this.Request.Properties["MS_HttpConfiguration"] = new HttpConfiguration();
    }

    this.Validate(queryData);

    if (ModelState.IsValid)
    {
        DoSomething();
    }
}

也请查看以下问题: Validate fails in unit tests

答案 3 :(得分:0)

在WebAPI 5.2.7上:

[TestMethod]
public void MoviesController_Post_Without_Name()()
{
    // Arrange
    var model = new MovieModel();
    model.Name = "";

    controller.Request = new HttpRequestMessage();
    controller.Configuration = new HttpConfiguration();
    controller.Validate(model);

    // Act
    var result = controller.Post(model);

    // Assert
    ...

这篇文章对我有帮助:https://www.c-sharpcorner.com/article/unit-testing-controllers-in-web-api/