Web API 2 单元测试不考虑数据属性

DataAttributes not Respected in WebAPI2 Unit Tests

我正在尝试学习如何正确使用 WebApi2 项目的单元测试。在我过去的项目中,我经常使用 DataAnnotations 进行基本的模型验证。但是,它们在我的单元测试中似乎没有被正确触发。

在下面的示例中,实际的 API 控制器在收到真正的 HTTP 请求时表现正常。当我提交一个没有定义 ParrotTalk 的 JSON 对象时,它将 return 一个 BadRequest (400)。但是,TestMethod 似乎没有调用此规则。在不诉诸复杂方法的情况下,我该怎么做才能将其反映在我的单元测试中?这似乎应该可以正常工作 "out of the box",因为它们是内置的,并且是 MVC 中常用的功能。

这是我在 JSON 中上传的模型。

 public class ParrotModel
{
    [Required]
    public string ParrotTalk { get; set; }
}

这是控制器中的实际方法。

    [HttpPost]
    [Route("another-endpoint")]
    public IHttpActionResult CallParrotFromBody(ParrotModel Parrot)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }
        return Ok(new TestModel { SomeString = "Bawwwwwk! " + Parrot.ParrotTalk });
    }

这是我的测试方法。出于某种原因,当它运行时,ModelState.IsValid 是正确的...但在真实站点中 运行 不是!

    [TestMethod]
    public void CallParrotFromBody()
    {
        //good request
        var controller = new RichController();

        var result = controller.CallParrotFromBody(new ParrotModel { ParrotTalk = "Stuff" });
        OkNegotiatedContentResult<TestModel> okResult = result as OkNegotiatedContentResult<TestModel>;

        Assert.IsNotNull(okResult);
        Assert.IsInstanceOfType(okResult.Content, typeof(TestModel));
        Assert.AreEqual(okResult.Content.SomeString, "Bawwwwwk! " + "Stuff" );

        //bad request---WHY DOESN'T THIS WORK????
        var nullRequestController = new RichController();
        var nullRequestResult = nullRequestController.CallParrotFromBody(new ParrotModel { });
        BadRequestResult badResult = nullRequestResult as BadRequestResult;

        Assert.IsNotNull(badResult);
    }

在下图中,您可以清楚地看到代码的 IsValid 部分未被触发,因为未处理 [Required] 属性。只有在 MVC 应用程序外部(例如:从测试中)调用此方法时才会发生这种情况。

我认为您正在寻找的是单元测试与集成测试。

这里的问题是,当您进行单元测试时,您是在独立于其他组件和依赖项测试系统的一部分。在您的特定情况下,这意味着在测试控制器并将模型传递给它时,用于验证的应用程序部分未被初始化和使用。

为了测试当模型中出现错误时您的控制器是否正确运行,您实际上必须手动向控制器指示模型中存在错误,如下所示:

controller.ModelState.AddModelError("FieldName", "SomeError");

这样的事情会使模型无效,因此控制器中的 ModelState.IsValid 将 return false.

如果您想检查您的验证引擎是否实际运行正确 - 例如如果我传递一个需要空字段的对象,控制器会 return http 状态 400 Bad Request 吗?

这实际上是集成测试,它涉及所有组件和依赖项,它们链接在一起,因此获得与您在服务器上实际拥有应用程序 运行 时类似的体验。

单元测试和集成测试之间存在很大差异 - 在单元测试中,您单独测试应用程序的特定部分,有时您必须模仿 运行ning 应用程序中由其他人处理的行为和情况自动初始化的组件。 在集成测试中,您实际测试了这些位如何在接近真实 运行ning 应用程序的环境中协同工作。