aspnetcore/test/Microsoft.AspNetCore.Mvc.Ra.../Internal/PageActionInvokerTest.cs

259 lines
9.6 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public class PageActionInvokerTest : CommonResourceInvokerTest
{
protected override ResourceInvoker CreateInvoker(
IFilterMetadata[] filters,
Exception exception = null,
IActionResult result = null,
IList<IValueProviderFactory> valueProviderFactories = null)
{
var actionDescriptor = new CompiledPageActionDescriptor
{
ViewEnginePath = "/Index.cshtml",
RelativePath = "/Index.cshtml",
HandlerMethods = new List<HandlerMethodDescriptor>(),
HandlerTypeInfo = typeof(TestPage).GetTypeInfo(),
ModelTypeInfo = typeof(TestPage).GetTypeInfo(),
PageTypeInfo = typeof(TestPage).GetTypeInfo(),
};
var handlers = new List<Func<object, object[], Task<IActionResult>>>();
if (result != null)
{
handlers.Add((obj, args) => Task.FromResult(result));
actionDescriptor.HandlerMethods.Add(new HandlerMethodDescriptor()
{
HttpMethod = "GET",
Parameters = new List<HandlerParameterDescriptor>(),
});
}
else if (exception != null)
{
handlers.Add((obj, args) => Task.FromException<IActionResult>(exception));
actionDescriptor.HandlerMethods.Add(new HandlerMethodDescriptor()
{
HttpMethod = "GET",
Parameters = new List<HandlerParameterDescriptor>(),
});
}
var executor = new TestPageResultExecutor();
return CreateInvoker(
filters,
actionDescriptor,
executor,
handlers: handlers.ToArray());
}
private PageActionInvoker CreateInvoker(
IFilterMetadata[] filters,
CompiledPageActionDescriptor actionDescriptor,
PageResultExecutor executor = null,
PageActionInvokerCacheEntry cacheEntry = null,
ITempDataDictionaryFactory tempDataFactory = null,
IList<IValueProviderFactory> valueProviderFactories = null,
Func<object, object[], Task<IActionResult>>[] handlers = null,
RouteData routeData = null,
ILogger logger = null)
{
var diagnosticSource = new DiagnosticListener("Microsoft.AspNetCore");
var httpContext = new DefaultHttpContext();
var serviceCollection = new ServiceCollection();
if (executor == null)
{
executor = new PageResultExecutor(
Mock.Of<IHttpResponseStreamWriterFactory>(),
Mock.Of<ICompositeViewEngine>(),
Mock.Of<IRazorViewEngine>(),
Mock.Of<IRazorPageActivator>(),
diagnosticSource,
HtmlEncoder.Default);
}
var mvcOptionsAccessor = new TestOptionsManager<MvcOptions>();
serviceCollection.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance);
serviceCollection.AddSingleton<IOptions<MvcOptions>>(mvcOptionsAccessor);
serviceCollection.AddSingleton(new ObjectResultExecutor(
mvcOptionsAccessor,
new TestHttpResponseStreamWriterFactory(),
NullLoggerFactory.Instance));
httpContext.Response.Body = new MemoryStream();
httpContext.RequestServices = serviceCollection.BuildServiceProvider();
serviceCollection.AddSingleton(executor ?? executor);
httpContext.RequestServices = serviceCollection.BuildServiceProvider();
if (routeData == null)
{
routeData = new RouteData();
}
var actionContext = new ActionContext(
httpContext: httpContext,
routeData: routeData,
actionDescriptor: actionDescriptor);
var pageContext = new PageContext(actionContext)
{
ActionDescriptor = actionDescriptor,
};
var viewDataFactory = ViewDataDictionaryFactory.CreateFactory(actionDescriptor.ModelTypeInfo);
pageContext.ViewData = viewDataFactory(new EmptyModelMetadataProvider(), pageContext.ModelState);
if (valueProviderFactories == null)
{
valueProviderFactories = new List<IValueProviderFactory>();
}
if (logger == null)
{
logger = NullLogger.Instance;
}
if (tempDataFactory == null)
{
tempDataFactory = Mock.Of<ITempDataDictionaryFactory>(m => m.GetTempData(It.IsAny<HttpContext>()) == Mock.Of<ITempDataDictionary>());
}
Func<PageContext, ViewContext, object> pageFactory = (context, viewContext) =>
{
var instance = (Page)Activator.CreateInstance(actionDescriptor.PageTypeInfo.AsType());
instance.PageContext = context;
return instance;
};
cacheEntry = new PageActionInvokerCacheEntry(
actionDescriptor,
viewDataFactory,
pageFactory,
(c, viewContext, page) => { (page as IDisposable)?.Dispose(); },
_ => Activator.CreateInstance(actionDescriptor.ModelTypeInfo.AsType()),
(c, model) => { (model as IDisposable)?.Dispose(); },
null,
handlers,
null,
new FilterItem[0]);
// Always just select the first one.
var selector = new Mock<IPageHandlerMethodSelector>();
selector
.Setup(s => s.Select(It.IsAny<PageContext>()))
.Returns<PageContext>(c => c.ActionDescriptor.HandlerMethods.FirstOrDefault());
var invoker = new PageActionInvoker(
selector.Object,
diagnosticSource,
logger,
pageContext,
filters,
valueProviderFactories.ToArray(),
cacheEntry,
GetParameterBinder(),
tempDataFactory,
new HtmlHelperOptions());
return invoker;
}
private static ParameterBinder GetParameterBinder(
IModelBinderFactory factory = null,
IObjectModelValidator validator = null)
{
if (validator == null)
{
validator = CreateMockValidator();
}
if (factory == null)
{
factory = TestModelBinderFactory.CreateDefault();
}
return new ParameterBinder(
TestModelMetadataProvider.CreateDefaultProvider(),
factory,
validator);
}
private static IObjectModelValidator CreateMockValidator()
{
var mockValidator = new Mock<IObjectModelValidator>(MockBehavior.Strict);
mockValidator
.Setup(o => o.Validate(
It.IsAny<ActionContext>(),
It.IsAny<ValidationStateDictionary>(),
It.IsAny<string>(),
It.IsAny<object>()));
return mockValidator.Object;
}
private class TestPageResultExecutor : PageResultExecutor
{
private readonly Func<PageContext, Task> _executeAction;
public TestPageResultExecutor()
: this(null)
{
}
public TestPageResultExecutor(Func<PageContext, Task> executeAction)
: base(
Mock.Of<IHttpResponseStreamWriterFactory>(),
Mock.Of<ICompositeViewEngine>(),
Mock.Of<IRazorViewEngine>(),
Mock.Of<IRazorPageActivator>(),
new DiagnosticListener("Microsoft.AspNetCore"),
HtmlEncoder.Default)
{
_executeAction = executeAction;
}
public override Task ExecuteAsync(PageContext pageContext, PageResult result)
{
return _executeAction?.Invoke(pageContext) ?? Task.CompletedTask;
}
}
private class TestPage : Page
{
public override Task ExecuteAsync()
{
throw new NotImplementedException();
}
}
}
}