2016-06-01 5 views
7

Я попытался сделать это и сделал много поисков google/stackoverflow без всякой удачи.ModelState.IsValid всегда верно при тестировании контроллера в Asp.Net MVC Web Api

У меня есть простая модель:

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.

Я пробовал много подходов до сих пор без успеха.

ответ

5

Ваше решение, вероятно, работает, но лучший способ - использовать метод ApiController.Validate.

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

    // Act 
    controller.Validate(model); //<---- use the built-in method 
    var result = controller.Post(model); 

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

Я пробовал этот .Validate метод раньше, но его не существует. Я использую MVC 5. –

+0

Ссылка Microsoft показывает метод Validate для версии 5 MVC, но она просто не работает, ни Intellisense, ни сборка не работают. –

+0

@ AndréBaptista Почему вы говорите о MVC? 'ApiController' - это класс веб-API, который находится в' System.Web.Http'. Убедитесь, что вы добавили правильные пакеты NuGet в тестовый проект. –

4

Благодаря 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()); 
} 

Надежда, что помогает кому-то, это спасло бы меня несколько часов в Интернете.

+0

это работает для меня, но не с вложенными моделями – MattjeS

+1

работал на Ядра 2.0, для вложен просто сделать 'SimulateValidation (модели); SimulateValidation (model.child); ' – ono2012

+0

Большое вам спасибо @Andre Baptista, это работает для меня –

 Смежные вопросы

  • Нет связанных вопросов^_^