【问题标题】:Model state validation in unit tests单元测试中的模型状态验证
【发布时间】:2013-06-25 04:10:24
【问题描述】:

我正在为这样的控制器编写单元测试:

public HttpResponseMessage PostLogin(LoginModel model)
{
    if (!ModelState.IsValid)
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
}

模型看起来像:

public class LoginModel
{
    [Required]
    public string Username { set; get; }
    [Required]
    public string Password { set; get; }
}

然后我有这样的单元测试:

[TestMethod]
public void TestLogin_InvalidModel()
{
    AccountController controller = CreateAccountController();

    ...
    var response = controller.PostLogin(new LoginModel() {  });

    Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

}

实际上 ModelState 已经过验证...这对我来说很奇怪,因为这两个字段都是必需的... 有人可以建议吗?

【问题讨论】:

标签: c# unit-testing asp.net-web-api vs-unit-testing-framework model-validation


【解决方案1】:

我无法获得响应对象的 response.StatusCode 属性。所以我不得不断言如下,这对我很有用。

IHttpActionResult actionResult = controller.ActionMethod(request);

Assert.IsInstanceOf(actionResult);

有没有办法检查响应对象的状态码? 比如说。 Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);

【讨论】:

    【解决方案2】:

    我在单元测试 Visual Studio 2017、C#、NET 4.x.x 中使用以下代码验证模型状态

       [TestMethod]
            public void TestYourValidationModel()
            {
                var configuration = new HttpConfiguration();
                configuration.Filters.Add(new ValidateModelAttribute());
                // Get the quote
                var controller = new YourController
                {
                    Request = new HttpRequestMessage(),
                    Configuration = configuration
                };
                var request = YourRequestObject;
                controller.Request.Content = new ObjectContent<YourRequestType>(
                    request, new JsonMediaTypeFormatter(), "application/json");
                controller.Validate(request);
                Assert.IsTrue(controller.ModelState.IsValid, "This must be valid");
            }
    

    该示例适用于 JSON 格式的请求。将 YourController 替换为控制器的名称,将 YourRequesType 替换为请求的对象类型。

    这使您可以选择在不使用服务的情况下测试您的模型以进行验证。

    【讨论】:

      【解决方案3】:

      如前所述,您需要集成测试来验证 ModelState。因此,对于 Asp.Net Core,我正在挖掘这个问题以添加一个简单的解决方案,用于将测试与 Asp.Net Core 集成并验证 ModelState

      添加包Microsoft.AspNetCore.TestHost,你就可以这么简单地提交请求了:

      var server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
      var client = server.CreateClient();
      var model = new { Name = String.Empty };
      var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
      var result = await client.PostAsync("/api/yourApiEndpoint", content);
      result.StatusCode.Should().Be(HttpStatusCode.BadRequest);
      

      您可以在此处找到更多相关信息: http://asp.net-hacker.rocks/2017/09/27/testing-aspnetcore.html

      希望对你有帮助。

      【讨论】:

      • 如果您正在寻找 .net 核心答案,那是正确的答案。
      • 注意,如果你喜欢更少的代码,你可以简单地使用await client.PostAsJsonAsync("api/v1/endpoint", object);
      【解决方案4】:

      TL;DR 如果您不想阅读 Youssef 提供的整篇文章并想快速解决如何使 ModelState.IsValid 返回 false。做这个。

      [TestMethod]
      public void TestLogin_InvalidModel()
      {
          AccountController controller = CreateAccountController();
          // new code added -->
          controller.ModelState.AddModelError("fakeError", "fakeError");
          // end of new code
          ...
          var response = controller.PostLogin(new LoginModel() {  });
      
          Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
      
      }
      

      现在我可以想象 CreateAccountController() 至少看起来像这样 ->

      return new AccountApiController()
      {
          Request = new HttpRequestMessage(),
          Configuration = new HttpConfiguration()
      };
      

      希望这能为那些在谷歌上搜索的人提供一个快速的答案:)

      【讨论】:

      • 感谢您的示例。我所做的唯一区别是断言的类型: Assert.IsInstanceOfType(actResult, typeof(InvalidModelStateResult));
      【解决方案5】:

      模型状态有效的原因是当您新建一个控制器时会创建一个新的模型状态。 Web API 并没有在这里为你做参数绑定,所以它甚至没有机会添加模型状态错误。

      如果你想把它作为一个单元测试,那么你应该自己添加模型状态错误并测试会发生什么。

      如果您想测试模型状态在实际请求中是否无效,我建议您阅读这篇博文:

      http://blogs.msdn.com/b/youssefm/archive/2013/01/28/writing-tests-for-an-asp-net-webapi-service.aspx

      并尝试针对内存服务器进行测试。对于您的情况,需要注意的一点是,您可能希望在请求中使用 StringContent 而不是 ObjectContent,以确保 Web API 尝试正确反序列化和绑定正文。

      【讨论】:

      猜你喜欢
      • 2012-05-03
      • 2018-10-08
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      相关资源
      最近更新 更多