【问题标题】:ASP.NET Core Integration Test for controller action用于控制器操作的 ASP.NET Core 集成测试
【发布时间】:2017-02-22 09:07:55
【问题描述】:

Microsoft 文档 (https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing) 解释了如何使用 TestServer 类实现集成测试。如果我们使用 WEB API,这很容易,因为我们将序列化模型作为操作的响应。

但如果我想测试返回包含一些数据的 HTML 视图的控制器操作,我如何评估页面内容是否符合我的预期(避免扫描 HTML 页面内容)?

【问题讨论】:

    标签: asp.net-core asp.net-core-mvc integration-testing


    【解决方案1】:

    一种选择是使用 Selenium 之类的自动化 UI 测试

    【讨论】:

      【解决方案2】:

      为了将此 JSON 序列化视图模型附加到您的页面,我实现了以下过滤器:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using Microsoft.AspNetCore.Http;
      using Microsoft.AspNetCore.Mvc;
      using Microsoft.AspNetCore.Mvc.Filters;
      using Microsoft.AspNetCore.Mvc.ModelBinding;
      using Newtonsoft.Json;
      using Ticketino.Web.Components.Extensions.Request;
      using Ticketino.Web.OnlineShop.Serializations;
      using Ticketino.Web.OnlineShop.ViewModels.Base;
      
      namespace Ticketino.Web.OnlineShop.Filters
      {
          /// <summary>
          /// This is a filter used only for integration tests.
          /// It format the ViewModel as jSon and appends it to the end of HMTL page, so that it can be deserialized from the test in order to check its values.
          /// </summary>
          /// <seealso cref="Microsoft.AspNetCore.Mvc.Filters.ResultFilterAttribute" />
          [AttributeUsage(AttributeTargets.Method)]
          public class IntegrationTestFilterAttribute : ResultFilterAttribute
          {
              public const string StartViewModelContainer = "<script type=\"model/json\">";
              public const string EndViewModelContainer = "</script>";
      
              public override void OnResultExecuting(ResultExecutingContext filterContext)
              {
                  if (!filterContext.ModelState.IsValid)
                  {
                      var viewResult = filterContext.Result as ViewResult;
                      if (viewResult?.Model is BaseViewModel)
                      {
                          var errors = IntegrationTestFilterAttribute.GetModelErrors(filterContext.ModelState);
                          ((BaseViewModel)viewResult.Model).ValidationErrors = errors;
                      }
                  }
      
                  base.OnResultExecuting(filterContext);
              }
      
              public override void OnResultExecuted(ResultExecutedContext filterContext)
              {
                  if (!filterContext.HttpContext.Request.IsAjaxRequest())
                  {
                      var viewResult = filterContext.Result as ViewResult;
                      if (viewResult?.Model != null)
                      {
                          var jsonViewModel = string.Concat(
                              IntegrationTestFilterAttribute.StartViewModelContainer,
                              JsonConvert.SerializeObject(viewResult.Model, Formatting.None, CommonJsonSerializerSettings.Settings()),
                              IntegrationTestFilterAttribute.EndViewModelContainer);
      
                          filterContext.HttpContext.Response.WriteAsync(jsonViewModel);
                      }
                  }
      
                  base.OnResultExecuted(filterContext);
              }
      
              #region Private methods
      
              private static IDictionary<string, string> GetModelErrors(ModelStateDictionary errDictionary)
              {
                  var errors = new Dictionary<string, string>();
      
                  //get all entries from the ModelStateDictionary that have any errors and add them to our Dictionary
                  errDictionary.Where(k => k.Value.Errors.Count > 0).ForEach(i =>
                  {
                      foreach (var errorMessage in i.Value.Errors.Select(e => e.ErrorMessage))
                      {
                          errors.Add(i.Key, errorMessage);
                      }
                  });
      
                  return errors;
              }
      
              #endregion
          }
      }
      

      然后,在 ConfigureServices(IServiceCollection serviceCollection) 方法中,当您运行集成测试时注入它,如下所示:

              // Filter to append json serialized view model to buttom html response page, in order to eveluate from integration test class
              if (_hostingEnvironment.IsIntegrationTest())
              {
                  mvcBuilder.AddMvcOptions(opt => { opt.Filters.Add(new IntegrationTestFilterAttribute()); });
              }
      

      【讨论】:

        猜你喜欢
        • 2017-05-13
        • 2022-08-17
        • 2017-12-12
        • 1970-01-01
        • 2018-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多