2017-02-22 2 views
0

Microsoft 설명서 (https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing)는 TestServer 클래스를 사용하여 통합 테스트를 구현하는 방법을 설명합니다. 액션에서 응답으로 직렬화 된 모델을 얻으므로 WEB API를 사용하는 경우 쉽습니다.ASP.NET 코어 통합 테스트 컨트롤러 동작

그러나 일부 데이터가 포함 된 HTML보기를 반환하는 컨트롤러 동작을 테스트하려는 경우 어떻게 HTML 페이지 내용을 스캔하지 않아도되는지 예상 할 수 있습니까?

답변

0

하나의 옵션은 셀레늄 같은 것을 사용하여 자동화 된 UI 테스트를 사용하는 것입니다

0

당신이 설정 한 하나 귀하의 WebHostBuilder을뿐만 아니라 TESTSERVER 개체로, 당신은 당신의 HTML 렌더링 된 페이지에 작성에 사용 된 JSON 직렬화 된 모델을 추가 할 수 있습니다 콘텐츠보기. 예를 들어 :

<!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; 
    } 

을 그 결과를 평가하는 데 사용 후. 보기에서 사용되는 뷰 모델은 "GreetingViewModel"이라고 가정하면, 단지 어떻게 그런 다음

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 
    } 
} 

:

이 페이지에이 JSON 직렬화보기 모델을 추가하기 위해
  var greetingViewModel = GetModel<GreetingViewModel>(resonseContent); 

      Assert.AreEqual(greetingViewModel.Message, "Ciao"); 
      Assert.AreEqual(greetingViewModel.Subject, "Kiss Me"); 

, 나는 다음과 같은 필터를 구현 , 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()); }); 
     } 
관련 문제