控制器的原因.UpdateModel不会用单元测试的全球化验证属性来验证模型

本文关键字:验证 属性 全球化 模型 单元测试 UpdateModel 控制器 | 更新日期: 2023-09-27 17:51:07

我创建了一个ASP。. NET MVC 5应用程序,使用以下模型类在其Email属性上使用全球化的 Required validation属性:

public class Person
{
    [Required(ErrorMessageResourceType = typeof(Resources),
              ErrorMessageResourceName = "EmptyEmailError")]
    public string Email { get; set; }
}

PersonController类的Create POST动作方法是:

[HttpPost]
public ActionResult Create(FormCollection formData)
{
    Person newPerson = new Person();
    UpdateModel(newPerson, formData);
    if (ModelState.IsValid) {
        // code to create the new person
        return View("Index", newPerson);
    }
    else {
        return View();
    }
}

验证没有创建具有空电子邮件地址的人的测试用例是:

[TestMethod]
void Create_DoesNotCreatePerson_WhenEmailIsEmpty()
{
    // arrange
    FormCollection person = new FormCollection() { { "Email", string.Empty } };
    PersonController controller = new PersonController();
    controller.ControllerContext = new ControllerContext();
    // act
    controller.Create(person);
    // assert
    Assert.IsFalse(controller.ModelState.IsValid);
}

有了这段代码,正常的执行工作得很好。但是,测试没有通过,这意味着UpdateModel返回true,因此没有正确验证人员模型。TryUpdateModel方法也不起作用

但是如果我从Person类的Required验证属性中删除ErrorMessage参数(即保留它为[Required]),则测试通过。

所以我不知道为什么当我从测试用例调用Create动作方法时,UpdateModel不验证全球化的Person模型。

控制器的原因.UpdateModel不会用单元测试的全球化验证属性来验证模型

我很高兴看到你正在为你的代码编写单元测试:)

首先,你为什么不直接通过Person,你真的需要FormCollection吗?

[TestMethod]
void Create_DoesNotCreatePerson_WhenEmailIsEmpty()
{
    // arrange
    FormCollection person = new FormCollection() { { "Email", string.Empty } };
    PersonController controller = new PersonController();
    controller.ControllerContext = new ControllerContext();
    // third, you might need to add this (haven't tested this)
    controller.ModelState.AddModelError("Email", "fakeError");
    // act
    controller.Create(person);
    // assert
    Assert.IsFalse(controller.ModelState.IsValid);
}

第四个也是最重要的。我认为你不应该这样测试。您需要针对不同的场景测试结果。这意味着您需要测试方法的返回值。当你说Assert.IsFalse(controller.ModelState.IsValid);时,你基本上是在说你不相信微软的代码,你想测试他们的代码。我可以向你保证他们的代码有单元测试,你不需要再测试了;)

应该测试从操作结果返回什么视图和返回什么对象。这里有一篇关于如何对此进行单元测试的完整文章-> https://msdn.microsoft.com/en-us/library/gg416511(VS.98).aspx(参见"为检索联系人创建测试")。希望这对你有帮助!

编辑(回复评论):

很抱歉响应时间过长。

我移到了"second"

如果你想测试真正的产品代码,你想做集成测试,而不是单元测试。如果单元测试是您想要的,我建议您遵循我的解决方案建议,否则创建集成测试。我不知道如何说服你,但我已经试过了,所以多读一些资料,我想你会同意在这种情况下如何进行单元测试:)

祝你好运!