Asp.net core 控制器操作的ASP.NET核心集成测试

Asp.net core 控制器操作的ASP.NET核心集成测试,asp.net-core,asp.net-core-mvc,integration-testing,Asp.net Core,Asp.net Core Mvc,Integration Testing,Microsoft文档()解释了如何使用TestServer类实现集成测试。在使用WEB API的情况下,这很容易,因为我们从操作中获得序列化模型作为响应 但是,如果我想测试返回包含一些数据的HTML视图的控制器操作,我如何评估页面内容是否符合我的预期(避免扫描HTML页面内容)?一个选项是使用Selenium之类的自动化UI测试,您已经设置了WebHostBuilder和TestServer对象,您可以将用于创建视图内容的JSON序列化模型附加到HTML呈现页面。例如: <!DOCTYP

Microsoft文档()解释了如何使用TestServer类实现集成测试。在使用WEB API的情况下,这很容易,因为我们从操作中获得序列化模型作为响应


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

一个选项是使用Selenium之类的自动化UI测试,您已经设置了WebHostBuilder和TestServer对象,您可以将用于创建视图内容的JSON序列化模型附加到HTML呈现页面。例如:

<!DOCTYPE html>
<html>
<head></head>
<body>    
    <div>Subject</div><div>Kiss Me</div>
    <div>Message</div><div>Ciao</div>
</body>
</html>

<script type="model/json">
  {"Date":"2017-02-22","Subject":"Kiss Me","Result":true,"Message":"Ciao"}
</script>
    public const string StartViewModelContainer = "<script type=\"model/json\">";
    public const string EndViewModelContainer = "</script>";

    protected virtual T GetModel<T>(string responseContent)
    {
        var result = default(T);

        if (!string.IsNullOrWhiteSpace(responseContent))
        {
            var index = responseContent.IndexOf(StartViewModelContainer, 0, StringComparison.InvariantCulture);
            if (index > 0)
            {
                var startingPosition = index + StartViewModelContainer.Length;

                var endingPosition = responseContent.IndexOf(
                    EndViewModelContainer,
                    startingPosition,
                    StringComparison.InvariantCulture);

                if (endingPosition <= startingPosition) return result;

                var jSonModel = responseContent.Substring(startingPosition, endingPosition - startingPosition);
                result = JsonConvert.DeserializeObject<T>(jSonModel);
            }
        }

        return result;
    }
            var greetingViewModel = GetModel<GreetingViewModel>(resonseContent);

            Assert.AreEqual(greetingViewModel.Message, "Ciao");
            Assert.AreEqual(greetingViewModel.Subject, "Kiss Me");
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
    }
}
        // 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()); });
        }