Я унаследовал приложение с модульным тестированием практически без тестов, и я пытаюсь смоделировать класс обслуживания.Класс принимает viewModel как строку, а модель как объект, а затем возвращает представление как строку.Похоже, разработчик реализовал нечто похожее на this .
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using FluidMvcViewEngine;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace Some.Api.Services
{
public class ViewRenderService
{
private readonly IActionContextAccessor _context;
private readonly IFluidViewEngine _fluidViewEngine;
private readonly ITempDataProvider _tempDataProvider;
public ViewRenderService(IActionContextAccessor context, IFluidViewEngine razorViewEngine, ITempDataProvider tempDataProvider)
{
_context = context;
_fluidViewEngine = razorViewEngine;
_tempDataProvider = tempDataProvider;
}
public async Task<string> RenderToStringAsync(string viewName, object model, CancellationToken ct = default(CancellationToken))
{
var actionContext = _context.ActionContext;
using (var writer = new StringWriter())
{
var viewResult = _fluidViewEngine.GetView(viewName, viewName, false);
if (viewResult.View == null)
{
throw new ArgumentNullException("exception message goes here");
}
var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
{
Model = model
};
var viewContext = new ViewContext(
actionContext,
viewResult.View,
viewDictionary,
new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),
writer,
new HtmlHelperOptions()
);
await viewResult.View.RenderAsync(viewContext);
return writer.ToString();
}
}
}
}
Код работает, но тестов для сервиса нет.Я смог все смоделировать с помощью nSubstitute, и он работает без исключений, но я действительно не понимаю, что writer.ToString()
должен писать или как его высмеивать.
Я вижу, что await viewResult.View.RenderAsync(viewContext);
отображает viewContext, и что ViewContext получает экземпляр StringWriter.Однако я не могу войти в метод ViewEngineResult.View.RenderAsync, чтобы увидеть, как работает StringWriter.
using System.Threading.Tasks;
using FluentAssertions;
using FluidMvcViewEngine;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using NSubstitute;
using Xunit;
namespace Some.Tests.UnitTests.Services
{
public class ViewRenderServiceTest
{
private readonly IActionContextAccessor _context;
private readonly IFluidViewEngine _fluidViewEngine;
private readonly ViewRenderService _service;
private readonly ITempDataProvider _tempDataProvider;
private readonly IView _view;
private readonly IViewEngine _viewEngine;
public ViewRenderServiceTest()
{
_context = Substitute.For<IActionContextAccessor>();
_fluidViewEngine = Substitute.For<IFluidViewEngine>();
_tempDataProvider = Substitute.For<ITempDataProvider>();
_view = Substitute.For<IView>();
_viewEngine = Substitute.For<IViewEngine>();
_service = new ViewRenderService(_context, _fluidViewEngine, _tempDataProvider);
}
[Fact]
public async Task RenderToStringAsyncTest()
{
// Arrange
var stringToRender = "RENDERED";
var someObject = new { Id = default(int), Name = "Bob" };
// Mock IActionContextAccessor
MockIActionContextAccessor();
// Mock IFluidViewEngine
MockIFluidViewEngine(stringToRender);
// Act
var test = await _service.RenderToStringAsync(stringToRender, someObject);
// Assert
test.Should().Be(stringToRender);
}
private void MockIActionContextAccessor()
{
var httpContext = Substitute.For<HttpContext>();
var routeData = Substitute.For<RouteData>();
var actionDescriptor = Substitute.For<ActionDescriptor>();
var modelState = Substitute.For<ModelStateDictionary>();
_context.ActionContext.Returns(new ActionContext(httpContext, routeData, actionDescriptor, modelState));
}
private void MockIFluidViewEngine(string stringToRender)
{
_view
.RenderAsync(Arg.Any<ViewContext>())
.Returns(Task.FromResult(stringToRender));
_view
.Path
.Returns(string.Empty);
_viewEngine
.GetView(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>())
.Returns(ViewEngineResult.Found(stringToRender, _view));
_fluidViewEngine
.GetView(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<bool>())
.Returns(ViewEngineResult.Found(stringToRender, _view));
}
}
}
Как только все было подключено, я ожидал увидеть RENDERED
, но все, что я получаюпустая строка.