Контроллер тестирования ASP MVC 3, вызывающий ModelState.IsValid, всегда возвращает true
У меня есть приложение ASP MVC 3, и в моей модели я реализовано IValidatableObject.
Когда мой контроллер отправляет сообщения для создания или редактирования, я, очевидно, хочу сохранить модель только в том случае, если она действительна.
Я вижу много блогов и сообщений и ответов, которые говорят что-то вроде
if(!ModelState.IsValid)
{
return View();
}
Мой вопрос. Почему ModelState.IsValid всегда верен в unit test на контроллере?
Пример:
[Test]
public void InValidModelsAreNotAdded()
{
var invalidModel = new MyModel() { SomeField = "some data", SomeOtherField = "" };
var result = _controller.Submit(invalidModel);
_repository.AssertWasNotCalled(r => r.Add(Arg.Is.Anything));
}
Код модели:
public class MyModel : IValidatableObject
{
public string SomeField { get; set; }
public string SomeOtherField { get; set; }
public IEnumerable Validate(ValidationContext validationContext)
{
if(string.IsNullOrWhiteSpace(SomeOtherField))
{
yield return
new ValidationResult("Oops invalid.", new[] {"SomeOtherField"});
}
}
}
AssertWasNotCalled всегда терпит неудачу в этом тесте.
Я прошел тест и заметил, что ModelState.IsValid верен для этого теста. Как будто IValidatableObject.Validate не вызывается. Кажется, что он работает, когда я запускаю проект, но это не очень помогает тестировать диск приложения.
Кроме того, я понимаю, что могу использовать атрибут [Required]
для моего примера, но мой реальный код имеет гораздо более сложную проверку.
Мысли?
Ответы
Ответ 1
Это правда, потому что вы не вызывали ничего, что устанавливает его false.
Это обычно происходит во время привязки, но поскольку вы просто передаете модель непосредственно в тесте, вы пропустите это вообще.
Если вы пытаетесь проверить проверку, сделайте это напрямую. Если вы пытаетесь проверить путь ошибки в своем контроллере, ваша организация тестирования может вызвать _controller.ModelState.AddModelError( //...
Ответ 2
Ну, если вы смоделируете поведение привязки модели, вы можете это сделать:
public class YourController : Controller
{
//some code
public ViewResult someAction(Model model)
{
try
{
ValidateModel(model);
}
catch
{
// deal with errors
}
}
//some code
}
ValidateModel с блоками "try catch" для меня гораздо более читабельны. Но вы все равно можете использовать блоки "if" с помощью метода TryValidateModel
Надеюсь, что это поможет!