Improvements to the MVC testing package
* Clean up unnecessary workarounds on the build project. * Remove the need to specify the content root relative to the solution and use a solution based on an assembly level attribute on the test assembly created at build time. * Remove non parameterless constructors. * Add support for creating specialized factories from the base factory and keep track of "child" factories for disposal. * Add support for creating clients that handle cookies and redirects automatically.
This commit is contained in:
parent
869825b16c
commit
908e7a863b
|
|
@ -32,7 +32,14 @@ namespace MvcSandbox
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.ConfigureLogging(factory =>
|
||||
{
|
||||
|
|
@ -42,11 +49,7 @@ namespace MvcSandbox
|
|||
})
|
||||
.UseIISIntegration()
|
||||
.UseKestrel()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
// 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.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Testing.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="DelegatingHandler"/> that manages cookies associated with one or
|
||||
/// more pairs of <see cref="HttpRequestMessage"/> and <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
public class CookieContainerHandler : DelegatingHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="CookieContainerHandler"/>.
|
||||
/// </summary>
|
||||
public CookieContainerHandler()
|
||||
: this(new CookieContainer())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="CookieContainerHandler"/>.
|
||||
/// </summary>
|
||||
/// <param name="cookieContainer">The <see cref="CookieContainer"/> to use for
|
||||
/// storing and retrieving cookies.
|
||||
/// </param>
|
||||
public CookieContainerHandler(CookieContainer cookieContainer)
|
||||
{
|
||||
Container = cookieContainer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="CookieContainer"/> used to store and retrieve cookies.
|
||||
/// </summary>
|
||||
public CookieContainer Container { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var cookieHeader = Container.GetCookieHeader(request.RequestUri);
|
||||
request.Headers.Add(HeaderNames.Cookie, cookieHeader);
|
||||
|
||||
var response = await base.SendAsync(request, cancellationToken);
|
||||
|
||||
if (response.Headers.TryGetValues(HeaderNames.SetCookie, out var setCookieHeaders))
|
||||
{
|
||||
foreach (var header in setCookieHeaders)
|
||||
{
|
||||
Container.SetCookies(response.RequestMessage.RequestUri, header);
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
// 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.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Testing.Handlers
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="DelegatingHandler"/> that follows redirect responses.
|
||||
/// </summary>
|
||||
public class RedirectHandler : DelegatingHandler
|
||||
{
|
||||
internal const int DefaultMaxRedirects = 7;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RedirectHandler"/>.
|
||||
/// </summary>
|
||||
public RedirectHandler()
|
||||
: this(maxRedirects: DefaultMaxRedirects)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="RedirectHandler"/>.
|
||||
/// </summary>
|
||||
/// <param name="maxRedirects">The maximun number of redirect responses to follow. It must be
|
||||
/// equal or greater than 0.</param>
|
||||
public RedirectHandler(int maxRedirects)
|
||||
{
|
||||
if (maxRedirects <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(maxRedirects));
|
||||
}
|
||||
|
||||
MaxRedirects = maxRedirects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum number of redirects this handler will follow.
|
||||
/// </summary>
|
||||
public int MaxRedirects { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
var remainingRedirects = MaxRedirects;
|
||||
|
||||
var originalRequestContent = HasBody(request) ? await DuplicateRequestContent(request) : null;
|
||||
var response = await base.SendAsync(request, cancellationToken);
|
||||
while (IsRedirect(response) && remainingRedirects >= 0)
|
||||
{
|
||||
remainingRedirects--;
|
||||
var redirectRequest = GetRedirectRequest(response, originalRequestContent);
|
||||
originalRequestContent = HasBody(redirectRequest) ? await DuplicateRequestContent(redirectRequest) : null;
|
||||
response = await base.SendAsync(redirectRequest, cancellationToken);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private static bool HasBody(HttpRequestMessage request) =>
|
||||
request.Method == HttpMethod.Post || request.Method == HttpMethod.Put;
|
||||
|
||||
private static async Task<HttpContent> DuplicateRequestContent(HttpRequestMessage request)
|
||||
{
|
||||
if (request.Content == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var originalRequestContent = request.Content;
|
||||
var (originalBody, copy) = await CopyBody(request);
|
||||
|
||||
var contentCopy = new StreamContent(copy);
|
||||
request.Content = new StreamContent(originalBody);
|
||||
|
||||
CopyContentHeaders(originalRequestContent, request.Content, contentCopy);
|
||||
|
||||
return contentCopy;
|
||||
}
|
||||
|
||||
private static void CopyContentHeaders(
|
||||
HttpContent originalRequestContent,
|
||||
HttpContent newRequestContent,
|
||||
HttpContent contentCopy)
|
||||
{
|
||||
foreach (var header in originalRequestContent.Headers)
|
||||
{
|
||||
contentCopy.Headers.Add(header.Key, header.Value);
|
||||
newRequestContent.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<(Stream originalBody, Stream copy)> CopyBody(HttpRequestMessage request)
|
||||
{
|
||||
var originalBody = await request.Content.ReadAsStreamAsync();
|
||||
var bodyCopy = new MemoryStream();
|
||||
await originalBody.CopyToAsync(bodyCopy);
|
||||
bodyCopy.Seek(0, SeekOrigin.Begin);
|
||||
if (originalBody.CanSeek)
|
||||
{
|
||||
originalBody.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
else
|
||||
{
|
||||
originalBody = new MemoryStream();
|
||||
await bodyCopy.CopyToAsync(originalBody);
|
||||
originalBody.Seek(0, SeekOrigin.Begin);
|
||||
bodyCopy.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
return (originalBody, bodyCopy);
|
||||
}
|
||||
|
||||
private static HttpRequestMessage GetRedirectRequest(
|
||||
HttpResponseMessage response,
|
||||
HttpContent originalContent)
|
||||
{
|
||||
var location = response.Headers.Location;
|
||||
if (!location.IsAbsoluteUri)
|
||||
{
|
||||
location = new Uri(
|
||||
new Uri(response.RequestMessage.RequestUri.GetLeftPart(UriPartial.Authority)),
|
||||
location);
|
||||
}
|
||||
|
||||
var redirect = !ShouldKeepVerb(response) ?
|
||||
new HttpRequestMessage(HttpMethod.Get, location) :
|
||||
new HttpRequestMessage(response.RequestMessage.Method, location)
|
||||
{
|
||||
Content = originalContent
|
||||
};
|
||||
|
||||
foreach (var header in response.RequestMessage.Headers)
|
||||
{
|
||||
redirect.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
|
||||
foreach (var property in response.RequestMessage.Properties)
|
||||
{
|
||||
redirect.Properties.Add(property.Key, property.Value);
|
||||
}
|
||||
|
||||
return redirect;
|
||||
}
|
||||
|
||||
private static bool ShouldKeepVerb(HttpResponseMessage response) =>
|
||||
response.StatusCode == HttpStatusCode.RedirectKeepVerb ||
|
||||
(int)response.StatusCode == 308;
|
||||
|
||||
private bool IsRedirect(HttpResponseMessage response) =>
|
||||
response.StatusCode == HttpStatusCode.MovedPermanently ||
|
||||
response.StatusCode == HttpStatusCode.Redirect ||
|
||||
response.StatusCode == HttpStatusCode.RedirectKeepVerb ||
|
||||
(int)response.StatusCode == 308;
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,20 @@ namespace Microsoft.AspNetCore.Mvc.Testing
|
|||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNetCore.Mvc.Testing.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// No method 'public static {0} CreateWebHostBuilder(string[] args)' found on '{1}'. Alternatively, {2} can be extended and 'protected virtual {0} {3}()' can be overridden to provide your own {0} instance.
|
||||
/// </summary>
|
||||
internal static string MissingCreateWebHostBuilderMethod
|
||||
{
|
||||
get => GetString("MissingCreateWebHostBuilderMethod");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// No method 'public static {0} CreateWebHostBuilder(string[] args)' found on '{1}'. Alternatively, {2} can be extended and 'protected virtual {0} {3}()' can be overridden to provide your own {0} instance.
|
||||
/// </summary>
|
||||
internal static string FormatMissingCreateWebHostBuilderMethod(object p0, object p1, object p2, object p3)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("MissingCreateWebHostBuilderMethod"), p0, p1, p2, p3);
|
||||
|
||||
/// <summary>
|
||||
/// Can't find'{0}'. This file is required for functional tests to run properly. There should be a copy of the file on your source project bin folder. If that is not the case, make sure that the property PreserveCompilationContext is set to true on your project file. E.g '<PreserveCompilationContext>true</PreserveCompilationContext>'. For functional tests to work they need to either run from the build output folder or the {1} file from your application's output directory must be copied to the folder where the tests are running on. A common cause for this error is having shadow copying enabled when the tests run.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
|
|
@ -26,36 +26,36 @@
|
|||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
|
|
@ -117,6 +117,9 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="MissingCreateWebHostBuilderMethod" xml:space="preserve">
|
||||
<value>No method 'public static {0} CreateWebHostBuilder(string[] args)' found on '{1}'. Alternatively, {2} can be extended and 'protected virtual {0} {3}()' can be overridden to provide your own {0} instance.</value>
|
||||
</data>
|
||||
<data name="MissingDepsFile" xml:space="preserve">
|
||||
<value>Can't find'{0}'. This file is required for functional tests to run properly. There should be a copy of the file on your source project bin folder. If that is not the case, make sure that the property PreserveCompilationContext is set to true on your project file. E.g '<PreserveCompilationContext>true</PreserveCompilationContext>'. For functional tests to work they need to either run from the build output folder or the {1} file from your application's output directory must be copied to the folder where the tests are running on. A common cause for this error is having shadow copying enabled when the tests run.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,345 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyModel;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// Factory for bootstrapping an application in memory for functional end to end tests.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntryPoint">A type in the entry point assembly of the application.
|
||||
/// Typically the Startup or Program classes can be used.</typeparam>
|
||||
public class WebApplicationFactory<TEntryPoint> : IDisposable where TEntryPoint : class
|
||||
{
|
||||
private TestServer _server;
|
||||
private Action<IWebHostBuilder> _configuration;
|
||||
private IList<HttpClient> _clients = new List<HttpClient>();
|
||||
private List<WebApplicationFactory<TEntryPoint>> _derivedFactories =
|
||||
new List<WebApplicationFactory<TEntryPoint>>();
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Creates an instance of <see cref="WebApplicationFactory{TEntryPoint}"/>. This factory can be used to
|
||||
/// create a <see cref="TestServer"/> instance using the MVC application defined by <typeparamref name="TEntryPoint"/>
|
||||
/// and one or more <see cref="HttpClient"/> instances used to send <see cref="HttpRequestMessage"/> to the <see cref="TestServer"/>.
|
||||
/// The <see cref="WebApplicationFactory{TEntryPoint}"/> will find the entry point class of <typeparamref name="TEntryPoint"/>
|
||||
/// assembly and initialize the application by calling <c>IWebHostBuilder CreateWebHostBuilder(string [] args)</c>
|
||||
/// on <typeparamref name="TEntryPoint"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This constructor will infer the application content root path by searching for a
|
||||
/// <see cref="WebApplicationFactoryContentRootAttribute"/> on the assembly containing the functional tests with
|
||||
/// a key equal to the <typeparamref name="TEntryPoint"/> assembly <see cref="Assembly.FullName"/>.
|
||||
/// In case an attribute with the right key can't be found, <see cref="WebApplicationFactory{TEntryPoint}"/>
|
||||
/// will fall back to searching for a solution file (*.sln) and then appending <typeparamref name="TEntryPoint"/> asembly name
|
||||
/// to the solution directory. The application root directory will be used to discover views and content files.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The application assemblies will be loaded from the dependency context of the assembly containing
|
||||
/// <typeparamref name="TEntryPoint" />. This means that project dependencies of the assembly containing
|
||||
/// <typeparamref name="TEntryPoint" /> will be loaded as application assemblies.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public WebApplicationFactory() :
|
||||
this(builder => { }, new WebApplicationFactoryClientOptions())
|
||||
{
|
||||
}
|
||||
|
||||
private WebApplicationFactory(Action<IWebHostBuilder> configuration, WebApplicationFactoryClientOptions options)
|
||||
{
|
||||
_configuration = configuration;
|
||||
ClientOptions = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="TestServer"/> created by this <see cref="WebApplicationFactory{TEntryPoint}"/>.
|
||||
/// </summary>
|
||||
public TestServer Server => _server;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IReadOnlyList{WebApplicationFactory}"/> of factories created from this factory
|
||||
/// by further customizing the <see cref="IWebHostBuilder"/> when calling
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}.WithWebHostBuilder(Action{IWebHostBuilder})"/>.
|
||||
/// </summary>
|
||||
public IReadOnlyList<WebApplicationFactory<TEntryPoint>> Factories => _derivedFactories.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="WebApplicationFactoryClientOptions"/> used by <see cref="CreateClient()"/>.
|
||||
/// </summary>
|
||||
public WebApplicationFactoryClientOptions ClientOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="WebApplicationFactory{TEntryPoint}"/> with a <see cref="IWebHostBuilder"/>
|
||||
/// that is further customized by <paramref name="configuration"/>.
|
||||
/// </summary>
|
||||
/// <param name="configuration">
|
||||
/// An <see cref="Action{IWebHostBuilder}"/> to configure the <see cref="IWebHostBuilder"/>.
|
||||
/// </param>
|
||||
/// <returns>A new <see cref="WebApplicationFactory{TEntryPoint}"/>.</returns>
|
||||
public WebApplicationFactory<TEntryPoint> WithWebHostBuilder(Action<IWebHostBuilder> configuration)
|
||||
{
|
||||
var factory = new WebApplicationFactory<TEntryPoint>(builder =>
|
||||
{
|
||||
_configuration(builder);
|
||||
configuration(builder);
|
||||
},
|
||||
new WebApplicationFactoryClientOptions(ClientOptions));
|
||||
|
||||
_derivedFactories.Add(factory);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
private void EnsureServer()
|
||||
{
|
||||
if (_server != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureDepsFile();
|
||||
|
||||
|
||||
var builder = CreateWebHostBuilder();
|
||||
SetContentRoot(builder);
|
||||
ConfigureWebHost(builder);
|
||||
_configuration(builder);
|
||||
_server = CreateServer(builder);
|
||||
}
|
||||
|
||||
private void SetContentRoot(IWebHostBuilder builder)
|
||||
{
|
||||
var metadataAttributes = GetContentRootMetadataAttributes(
|
||||
typeof(TEntryPoint).Assembly.FullName,
|
||||
typeof(TEntryPoint).Assembly.GetName().Name);
|
||||
|
||||
string contentRoot = null;
|
||||
for (var i = 0; i < metadataAttributes.Length; i++)
|
||||
{
|
||||
var contentRootAttribute = metadataAttributes[i];
|
||||
var contentRootCandidate = Path.Combine(
|
||||
AppContext.BaseDirectory,
|
||||
contentRootAttribute.ContentRootPath);
|
||||
|
||||
var contentRootMarker = Path.Combine(
|
||||
contentRootCandidate,
|
||||
Path.GetFileName(contentRootAttribute.ContentRootTest));
|
||||
|
||||
if (File.Exists(contentRootMarker))
|
||||
{
|
||||
contentRoot = contentRootCandidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (contentRoot != null)
|
||||
{
|
||||
builder.UseContentRoot(contentRoot);
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.UseSolutionRelativeContentRoot(typeof(TEntryPoint).Assembly.GetName().Name);
|
||||
}
|
||||
}
|
||||
|
||||
private WebApplicationFactoryContentRootAttribute[] GetContentRootMetadataAttributes(
|
||||
string tEntryPointAssemblyFullName,
|
||||
string tEntryPointAssemblyName)
|
||||
{
|
||||
var testAssembly = GetTestAssemblies();
|
||||
var metadataAttributes = testAssembly
|
||||
.SelectMany(a => a.GetCustomAttributes<WebApplicationFactoryContentRootAttribute>())
|
||||
.Where(a => string.Equals(a.Key, tEntryPointAssemblyFullName, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(a.Key, tEntryPointAssemblyName, StringComparison.OrdinalIgnoreCase))
|
||||
.OrderBy(a => a.Priority)
|
||||
.ToArray();
|
||||
|
||||
return metadataAttributes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assemblies containing the functional tests. The
|
||||
/// <see cref="WebApplicationFactoryContentRootAttribute"/> applied to these
|
||||
/// assemblies defines the content root to use for the given
|
||||
/// <typeparamref name="TEntryPoint"/>.
|
||||
/// </summary>
|
||||
/// <returns>The list of <see cref="Assembly"/> containing tests.</returns>
|
||||
protected virtual IEnumerable<Assembly> GetTestAssemblies()
|
||||
{
|
||||
try
|
||||
{
|
||||
// The default dependency context will be populated in .net core applications.
|
||||
var context = DependencyContext.Default;
|
||||
if (context != null)
|
||||
{
|
||||
// Find the list of projects
|
||||
var projects = context.CompileLibraries.Where(l => l.Type == "project");
|
||||
|
||||
// Find the list of projects runtime information and their assembly names.
|
||||
var runtimeProjectLibraries = context.RuntimeLibraries
|
||||
.Where(r => projects.Any(p => p.Name == r.Name))
|
||||
.ToDictionary(r => r, r => r.GetDefaultAssemblyNames(context).ToArray());
|
||||
|
||||
var entryPointAssemblyName = typeof(TEntryPoint).Assembly.GetName().Name;
|
||||
|
||||
// Find the project containing TEntryPoint
|
||||
var entryPointRuntimeLibrary = runtimeProjectLibraries
|
||||
.Single(rpl => rpl.Value.Any(a => string.Equals(a.Name, entryPointAssemblyName, StringComparison.Ordinal)));
|
||||
|
||||
// Find the list of projects referencing TEntryPoint.
|
||||
var candidates = runtimeProjectLibraries
|
||||
.Where(rpl => rpl.Key.Dependencies
|
||||
.Any(d => string.Equals(d.Name, entryPointRuntimeLibrary.Key.Name, StringComparison.Ordinal)));
|
||||
|
||||
return candidates.SelectMany(rl => rl.Value).Select(Assembly.Load);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The app domain friendly name will be populated in full framework.
|
||||
return new[] { Assembly.Load(AppDomain.CurrentDomain.FriendlyName) };
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
|
||||
return Array.Empty<Assembly>();
|
||||
}
|
||||
|
||||
private void EnsureDepsFile()
|
||||
{
|
||||
var depsFileName = $"{typeof(TEntryPoint).Assembly.GetName().Name}.deps.json";
|
||||
var depsFile = new FileInfo(Path.Combine(AppContext.BaseDirectory, depsFileName));
|
||||
if (!depsFile.Exists)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatMissingDepsFile(
|
||||
depsFile.FullName,
|
||||
Path.GetFileName(depsFile.FullName)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="IWebHostBuilder"/> used to set up <see cref="TestServer"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default implementation of this method looks for a <c>public static IWebHostBuilder CreateDefaultBuilder(string[] args)</c>
|
||||
/// method defined on the entry point of the assembly of <typeparamref name="TEntryPoint" /> and invokes it passing an empty string
|
||||
/// array as arguments.
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="IWebHostBuilder"/> instance.</returns>
|
||||
protected virtual IWebHostBuilder CreateWebHostBuilder() =>
|
||||
WebHostBuilderFactory.CreateFromTypesAssemblyEntryPoint<TEntryPoint>(Array.Empty<string>()) ??
|
||||
throw new InvalidOperationException(Resources.FormatMissingCreateWebHostBuilderMethod(
|
||||
nameof(IWebHostBuilder),
|
||||
typeof(TEntryPoint).Assembly.EntryPoint.DeclaringType.FullName,
|
||||
typeof(WebApplicationFactory<TEntryPoint>).Name,
|
||||
nameof(CreateWebHostBuilder)));
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="TestServer"/> with the bootstrapped application in <paramref name="builder"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IWebHostBuilder"/> used to
|
||||
/// create the server.</param>
|
||||
/// <returns>The <see cref="TestServer"/> with the bootstrapped application.</returns>
|
||||
protected virtual TestServer CreateServer(IWebHostBuilder builder) => new TestServer(builder);
|
||||
|
||||
/// <summary>
|
||||
/// Gives a fixture an opportunity to configure the application before it gets built.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IWebHostBuilder"/> for the application.</param>
|
||||
protected virtual void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="HttpClient"/> that automatically follows
|
||||
/// redirects and handles cookies.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="HttpClient"/>.</returns>
|
||||
public HttpClient CreateClient() =>
|
||||
CreateClient(ClientOptions);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of <see cref="HttpClient"/> that automatically follows
|
||||
/// redirects and handles cookies.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="HttpClient"/>.</returns>
|
||||
public HttpClient CreateClient(WebApplicationFactoryClientOptions options) =>
|
||||
CreateDefaultClient(options.BaseAddress, options.CreateHandlers());
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of an <see cref="HttpClient"/> that can be used to
|
||||
/// send <see cref="HttpRequestMessage"/> to the server. The base address of the <see cref="HttpClient"/>
|
||||
/// instance will be set to <c>http://localhost</c>.
|
||||
/// </summary>
|
||||
/// <param name="handlers">A list of <see cref="DelegatingHandler"/> instances to set up on the
|
||||
/// <see cref="HttpClient"/>.</param>
|
||||
/// <returns>The <see cref="HttpClient"/>.</returns>
|
||||
public HttpClient CreateDefaultClient(params DelegatingHandler[] handlers) =>
|
||||
CreateDefaultClient(new Uri("http://localhost"), handlers);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of an <see cref="HttpClient"/> that can be used to
|
||||
/// send <see cref="HttpRequestMessage"/> to the server.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address of the <see cref="HttpClient"/> instance.</param>
|
||||
/// <param name="handlers">A list of <see cref="DelegatingHandler"/> instances to set up on the
|
||||
/// <see cref="HttpClient"/>.</param>
|
||||
/// <returns>The <see cref="HttpClient"/>.</returns>
|
||||
public HttpClient CreateDefaultClient(Uri baseAddress, params DelegatingHandler[] handlers)
|
||||
{
|
||||
EnsureServer();
|
||||
if (handlers == null || handlers.Length == 0)
|
||||
{
|
||||
var client = _server.CreateClient();
|
||||
client.BaseAddress = baseAddress;
|
||||
|
||||
return client;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = handlers.Length - 1; i > 0; i--)
|
||||
{
|
||||
handlers[i - 1].InnerHandler = handlers[i];
|
||||
}
|
||||
|
||||
var serverHandler = _server.CreateHandler();
|
||||
handlers[handlers.Length - 1].InnerHandler = serverHandler;
|
||||
|
||||
var client = new HttpClient(handlers[0])
|
||||
{
|
||||
BaseAddress = baseAddress
|
||||
};
|
||||
|
||||
_clients.Add(client);
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var client in _clients)
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
|
||||
foreach (var factory in _derivedFactories)
|
||||
{
|
||||
factory.Dispose();
|
||||
}
|
||||
|
||||
_server?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Mvc.Testing.Handlers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// The default options to use to when creating
|
||||
/// <see cref="HttpClient"/> instances by calling
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}.CreateClient(WebApplicationFactoryClientOptions)"/>.
|
||||
/// </summary>
|
||||
public class WebApplicationFactoryClientOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="WebApplicationFactoryClientOptions"/>.
|
||||
/// </summary>
|
||||
public WebApplicationFactoryClientOptions()
|
||||
{
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
internal WebApplicationFactoryClientOptions(WebApplicationFactoryClientOptions clientOptions)
|
||||
{
|
||||
BaseAddress = clientOptions.BaseAddress;
|
||||
AllowAutoRedirect = clientOptions.AllowAutoRedirect;
|
||||
MaxAutomaticRedirections = clientOptions.MaxAutomaticRedirections;
|
||||
HandleCookies = clientOptions.HandleCookies;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the base address of <see cref="HttpClient"/> instances created by calling
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}.CreateClient(WebApplicationFactoryClientOptions)"/>.
|
||||
/// The default is <c>http://localhost</c>.
|
||||
/// </summary>
|
||||
public Uri BaseAddress { get; set; } = new Uri("http://localhost");
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether or not <see cref="HttpClient"/> instances created by calling
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}.CreateClient(WebApplicationFactoryClientOptions)"/>
|
||||
/// should automatically follow redirect responses.
|
||||
/// The default is <c>true</c>.
|
||||
/// /// </summary>
|
||||
public bool AllowAutoRedirect { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of redirect responses that <see cref="HttpClient"/> instances
|
||||
/// created by calling <see cref="WebApplicationFactory{TEntryPoint}.CreateClient(WebApplicationFactoryClientOptions)"/>
|
||||
/// should follow.
|
||||
/// The default is <c>7</c>.
|
||||
/// </summary>
|
||||
public int MaxAutomaticRedirections { get; set; } = RedirectHandler.DefaultMaxRedirects;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether <see cref="HttpClient"/> instances created by calling
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}.CreateClient(WebApplicationFactoryClientOptions)"/>
|
||||
/// should handle cookies.
|
||||
/// The default is <c>true</c>.
|
||||
/// </summary>
|
||||
public bool HandleCookies { get; set; } = true;
|
||||
|
||||
internal DelegatingHandler[] CreateHandlers()
|
||||
{
|
||||
return CreateHandlersCore().ToArray();
|
||||
|
||||
IEnumerable<DelegatingHandler> CreateHandlersCore()
|
||||
{
|
||||
if (AllowAutoRedirect)
|
||||
{
|
||||
yield return new RedirectHandler(MaxAutomaticRedirections);
|
||||
}
|
||||
if (HandleCookies)
|
||||
{
|
||||
yield return new CookieContainerHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// 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.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata that <see cref="WebApplicationFactory{TEntryPoint}"/> uses to find out the content
|
||||
/// root for the web application represented by <c>TEntryPoint</c>.
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}"/> will iterate over all the instances of
|
||||
/// <see cref="WebApplicationFactoryContentRootAttribute"/>, filter the instances whose
|
||||
/// <see cref="Key"/> is equal to <c>TEntryPoint</c> <see cref="Assembly.FullName"/>,
|
||||
/// order them by <see cref="Priority"/> in ascending order.
|
||||
/// <see cref="WebApplicationFactory{TEntryPoint}"/> will check for the existence of the marker
|
||||
/// in <code>Path.Combine(<see cref="ContentRootPath"/>, Path.GetFileName(<see cref="ContentRootTest"/>))"</code>
|
||||
/// and if the file exists it will set the content root to <see cref="ContentRootPath"/>.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)]
|
||||
public sealed class WebApplicationFactoryContentRootAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="WebApplicationFactoryContentRootAttribute"/>.
|
||||
/// </summary>
|
||||
/// <param name="key">
|
||||
/// The key of this <see cref="WebApplicationFactoryContentRootAttribute"/>. This
|
||||
/// key is used by <see cref="WebApplicationFactory{TEntryPoint}"/> to determine what of the
|
||||
/// <see cref="WebApplicationFactoryContentRootAttribute"/> instances on the test assembly should be used
|
||||
/// to match a given TEntryPoint class.
|
||||
/// </param>
|
||||
/// <param name="contentRootPath">The path to the content root. This path can be either relative or absolute.
|
||||
/// In case the path is relative, the path will be combined with
|
||||
/// <code><see cref="Directory.GetCurrentDirectory()"/></code></param>
|
||||
/// <param name="contentRootTest">
|
||||
/// A file that will be use as a marker to determine that the content root path for the given context is correct.
|
||||
/// </param>
|
||||
/// <param name="priority">
|
||||
/// The priority of this content root attribute compared to other attributes. When
|
||||
/// multiple <see cref="WebApplicationFactoryContentRootAttribute"/> instances are applied for the
|
||||
/// same key, they are processed with <see cref="int.Parse(string)"/>, ordered in ascending order and applied
|
||||
/// in priority until a match is found.
|
||||
/// </param>
|
||||
public WebApplicationFactoryContentRootAttribute(
|
||||
string key,
|
||||
string contentRootPath,
|
||||
string contentRootTest,
|
||||
string priority)
|
||||
{
|
||||
Key = key;
|
||||
ContentRootPath = contentRootPath;
|
||||
ContentRootTest = contentRootTest;
|
||||
if (int.TryParse(priority, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedPriority))
|
||||
{
|
||||
Priority = parsedPriority;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the key for the content root associated with this project. Typically <see cref="Assembly.FullName"/>.
|
||||
/// </summary>
|
||||
public string Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content root path for a given project. This content root can be relative or absolute. If it is a
|
||||
/// relative path, it will be combined with <see cref="AppContext.BaseDirectory"/>.
|
||||
/// </summary>
|
||||
public string ContentRootPath { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A marker file used to ensure that the path the content root is being set to is correct.
|
||||
/// </summary>
|
||||
public string ContentRootTest { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a number for determining the probing order when multiple <see cref="WebApplicationFactoryContentRootAttribute"/>
|
||||
/// instances with the same key are present on the test <see cref="Assembly"/>.
|
||||
/// </summary>
|
||||
public int Priority { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,200 +0,0 @@
|
|||
// 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.IO;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Testing
|
||||
{
|
||||
/// <summary>
|
||||
/// Fixture for bootstrapping an application in memory for functional end to end tests.
|
||||
/// </summary>
|
||||
/// <typeparam name="TStartup">The applications startup class.</typeparam>
|
||||
public class WebApplicationTestFixture<TStartup> : IDisposable where TStartup : class
|
||||
{
|
||||
private readonly TestServer _server;
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Creates a TestServer instance using the MVC application defined by<typeparamref name="TStartup"/>.
|
||||
/// The startup code defined in <typeparamref name = "TStartup" /> will be executed to configure the application.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This constructor will infer the application root directive by searching for a solution file (*.sln) and then
|
||||
/// appending the path<c>{AssemblyName}</c> to the solution directory.The application root directory will be
|
||||
/// used to discover views and content files.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The application assemblies will be loaded from the dependency context of the assembly containing
|
||||
/// <typeparamref name = "TStartup" />.This means that project dependencies of the assembly containing
|
||||
/// <typeparamref name = "TStartup" /> will be loaded as application assemblies.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public WebApplicationTestFixture()
|
||||
: this(typeof(TStartup).Assembly.GetName().Name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Creates a TestServer instance using the MVC application defined by<typeparamref name="TStartup"/>.
|
||||
/// The startup code defined in <typeparamref name = "TStartup" /> will be executed to configure the application.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This constructor will infer the application root directive by searching for a solution file (*.sln) and then
|
||||
/// appending the path <paramref name="solutionRelativePath"/> to the solution directory.The application root
|
||||
/// directory will be used to discover views and content files.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The application assemblies will be loaded from the dependency context of the assembly containing
|
||||
/// <typeparamref name = "TStartup" />.This means that project dependencies of the assembly containing
|
||||
/// <typeparamref name = "TStartup" /> will be loaded as application assemblies.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="solutionRelativePath">The path to the project folder relative to the solution file of your
|
||||
/// application. The folder of the first .sln file found traversing up the folder hierarchy from the test execution
|
||||
/// folder is considered as the base path.</param>
|
||||
protected WebApplicationTestFixture(string solutionRelativePath)
|
||||
: this("*.sln", solutionRelativePath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Creates a TestServer instance using the MVC application defined by<typeparamref name="TStartup"/>.
|
||||
/// The startup code defined in <typeparamref name = "TStartup" /> will be executed to configure the application.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This constructor will infer the application root directive by searching for a solution file that matches the pattern
|
||||
/// <paramref name="solutionSearchPattern"/> and then appending the path <paramref name="solutionRelativePath"/>
|
||||
/// to the solution directory.The application root directory will be used to discover views and content files.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The application assemblies will be loaded from the dependency context of the assembly containing
|
||||
/// <typeparamref name = "TStartup" />.This means that project dependencies of the assembly containing
|
||||
/// <typeparamref name = "TStartup" /> will be loaded as application assemblies.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="solutionSearchPattern">The glob pattern to use when searching for a solution file by
|
||||
/// traversing up the folder hierarchy from the test execution folder.</param>
|
||||
/// <param name="solutionRelativePath">The path to the project folder relative to the solution file of your
|
||||
/// application. The folder of the first sln file that matches the <paramref name="solutionSearchPattern"/>
|
||||
/// found traversing up the folder hierarchy from the test execution folder is considered as the base path.</param>
|
||||
protected WebApplicationTestFixture(string solutionSearchPattern, string solutionRelativePath)
|
||||
{
|
||||
EnsureDepsFile();
|
||||
|
||||
var builder = CreateWebHostBuilder();
|
||||
builder
|
||||
.UseStartup<TStartup>()
|
||||
.UseSolutionRelativeContentRoot(solutionRelativePath);
|
||||
|
||||
ConfigureWebHost(builder);
|
||||
_server = CreateServer(builder);
|
||||
|
||||
Client = CreateClient();
|
||||
}
|
||||
|
||||
private void EnsureDepsFile()
|
||||
{
|
||||
var depsFileName = $"{typeof(TStartup).Assembly.GetName().Name}.deps.json";
|
||||
var depsFile = new FileInfo(Path.Combine(AppContext.BaseDirectory, depsFileName));
|
||||
if (!depsFile.Exists)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatMissingDepsFile(
|
||||
depsFile.FullName,
|
||||
Path.GetFileName(depsFile.FullName)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="IWebHostBuilder"/> used to setup <see cref="TestServer"/>.
|
||||
/// <remarks>
|
||||
/// The default implementation of this method looks for a <c>public static IWebHostBuilder CreateDefaultBuilder(string[] args)</c>
|
||||
/// method defined on the entry point of the assembly of <typeparamref name="TStartup" /> and invokes it passing an empty string
|
||||
/// array as arguments. In case this method can't be found,
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="IWebHostBuilder"/> instance.</returns>
|
||||
protected virtual IWebHostBuilder CreateWebHostBuilder() =>
|
||||
WebHostBuilderFactory.CreateFromTypesAssemblyEntryPoint<TStartup>(Array.Empty<string>()) ?? new WebHostBuilder();
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="TestServer"/> with the bootstrapped application in <paramref name="builder"/>.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IWebHostBuilder"/> used to
|
||||
/// create the server.</param>
|
||||
/// <returns>The <see cref="TestServer"/> with the bootstrapped application.</returns>
|
||||
protected virtual TestServer CreateServer(IWebHostBuilder builder) => new TestServer(builder);
|
||||
|
||||
/// <summary>
|
||||
/// Gives a fixture an opportunity to configure the application before it gets built.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IWebHostBuilder"/> for the application.</param>
|
||||
protected virtual void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an instance of the <see cref="HttpClient"/> used to send <see cref="HttpRequestMessage"/> to the server.
|
||||
/// </summary>
|
||||
public HttpClient Client { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of an <see cref="HttpClient"/> that can be used to
|
||||
/// send <see cref="HttpRequestMessage"/> to the server.
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="HttpClient"/></returns>
|
||||
public HttpClient CreateClient()
|
||||
{
|
||||
var client = _server.CreateClient();
|
||||
client.BaseAddress = new Uri("http://localhost");
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of an <see cref="HttpClient"/> that can be used to
|
||||
/// send <see cref="HttpRequestMessage"/> to the server.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address of the <see cref="HttpClient"/> instance.</param>
|
||||
/// <param name="handlers">A list of <see cref="DelegatingHandler"/> instances to setup on the
|
||||
/// <see cref="HttpClient"/>.</param>
|
||||
/// <returns>The <see cref="HttpClient"/>.</returns>
|
||||
public HttpClient CreateClient(Uri baseAddress, params DelegatingHandler[] handlers)
|
||||
{
|
||||
if (handlers == null || handlers.Length == 0)
|
||||
{
|
||||
var client = _server.CreateClient();
|
||||
client.BaseAddress = baseAddress;
|
||||
|
||||
return client;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
for (var i = handlers.Length - 1; i > 1; i--)
|
||||
{
|
||||
handlers[i - 1].InnerHandler = handlers[i];
|
||||
}
|
||||
|
||||
var serverHandler = _server.CreateHandler();
|
||||
handlers[handlers.Length - 1].InnerHandler = serverHandler;
|
||||
var client = new HttpClient(handlers[0]);
|
||||
client.BaseAddress = baseAddress;
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Client.Dispose();
|
||||
_server.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,11 +15,43 @@
|
|||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CopyAditionalFiles" AfterTargets="Build" Condition="'$(TargetFramework)'!=''">
|
||||
<Target Name="_ResolveMvcTestProjectReferences" DependsOnTargets="ResolveReferences">
|
||||
<ItemGroup>
|
||||
<_ContentRootProjectReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference'" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="_AddContentRootForProjectReferences" BeforeTargets="BeforeCompile" DependsOnTargets="_ResolveMvcTestProjectReferences">
|
||||
<ItemGroup>
|
||||
<DepsFilePaths Include="$([System.IO.Path]::ChangeExtension('%(_ResolvedProjectReferencePaths.FullPath)', '.deps.json'))" />
|
||||
<WebApplicationFactoryContentRootAttribute
|
||||
Condition="'%(_ContentRootProjectReferences.Identity)' != ''"
|
||||
Include="%(_ContentRootProjectReferences.Identity)"
|
||||
AssemblyName="%(_ContentRootProjectReferences.FusionName)"
|
||||
ContentRootPath="$([System.IO.Path]::GetDirectoryName(%(_ContentRootProjectReferences.MSBuildSourceProjectFile)))"
|
||||
ContentRootTest="$([System.IO.Path]::GetFileName(%(_ContentRootProjectReferences.MSBuildSourceProjectFile)))"
|
||||
Priority="0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute
|
||||
Condition=" '%(WebApplicationFactoryContentRootAttribute.Identity)' != '' "
|
||||
Include="Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactoryContentRootAttribute">
|
||||
<_Parameter1>%(WebApplicationFactoryContentRootAttribute.AssemblyName)</_Parameter1>
|
||||
<_Parameter2>%(WebApplicationFactoryContentRootAttribute.ContentRootPath)</_Parameter2>
|
||||
<_Parameter3>%(WebApplicationFactoryContentRootAttribute.ContentRootTest)</_Parameter3>
|
||||
<_Parameter4>%(WebApplicationFactoryContentRootAttribute.Priority)</_Parameter4>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyAditionalFiles" AfterTargets="Build;_ResolveMvcTestProjectReferences" Condition="'$(TargetFramework)'!=''">
|
||||
<ItemGroup>
|
||||
<DepsFilePaths
|
||||
Condition="'%(_ContentRootProjectReferences.Identity)' != ''"
|
||||
Include="$([System.IO.Path]::ChangeExtension('%(_ContentRootProjectReferences.ResolvedFrom)', '.deps.json'))" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="%(DepsFilePaths.FullPath)" DestinationFolder="$(OutputPath)" Condition="Exists('%(DepsFilePaths.FullPath)')" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public AntiforgeryAuthTests(MvcTestFixture<Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public AntiforgeryTests(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ApiBehaviorTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ApiExplorerTest(MvcTestFixture<ApiExplorerWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ApplicationModelTest(MvcTestFixture<ApplicationModelWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public AsyncActionsTests(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public BasicTests(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public CombineAuthorizeTests(MvcTestFixture<StartupWithGlobalAuthorizeAndAllowCombiningAuthorizeFilters> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public CompilationOptionsTests(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ConsumesAttributeTests(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ContentNegotiationTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ControllerFromServicesTest(MvcTestFixture<ControllersFromServicesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public CorsTests(MvcTestFixture<CorsWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public DefaultOrderTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public DefaultValuesTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public DirectivesTest(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public DoNotRespectBrowserAcceptHeaderTests(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
"'Microsoft.NET.Sdk.Web' and the 'PreserveCompilationContext' property is not set to false.");
|
||||
public ErrorPageTests(MvcTestFixture<ErrorPageMiddlewareWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public FileResultTests(MvcTestFixture<FilesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public FiltersTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public FlushPointTest(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public FormFileUploadTest(MvcTestFixture<FilesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ using System.Linq;
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -13,9 +15,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public GlobalAuthorizationFilterTest(MvcTestFixture<SecurityWebSite.StartupWithGlobalDenyAnonymousFilter> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<SecurityWebSite.StartupWithGlobalDenyAnonymousFilter>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
@ -66,7 +72,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
Assert.Equal(
|
||||
"http://localhost/Home/Login?ReturnUrl=%2FAdministration%2FEitherCookie",
|
||||
response.Headers.Location.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -23,8 +23,8 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
MvcTestFixture<HtmlGenerationWebSite.Startup> fixture,
|
||||
MvcEncodedTestFixture<HtmlGenerationWebSite.Startup> encodedFixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
EncodedClient = encodedFixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
EncodedClient = encodedFixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public HtmlHelperOptionsTest(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
// 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.IO;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class MvcSampleFixture<TStartup> : MvcTestFixture<TStartup>
|
||||
where TStartup : class
|
||||
{
|
||||
public MvcSampleFixture() : base(Path.Combine("samples", typeof(TStartup).Assembly.GetName().Name)) { }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -9,19 +10,9 @@ using Microsoft.AspNetCore.TestHost;
|
|||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class MvcTestFixture<TStartup> : WebApplicationTestFixture<TStartup>
|
||||
public class MvcTestFixture<TStartup> : WebApplicationFactory<TStartup>
|
||||
where TStartup : class
|
||||
{
|
||||
public MvcTestFixture()
|
||||
: base(Path.Combine("test", "WebSites", typeof(TStartup).Assembly.GetName().Name))
|
||||
{
|
||||
}
|
||||
|
||||
protected MvcTestFixture(string solutionRelativePath)
|
||||
: base(solutionRelativePath)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder) =>
|
||||
builder.UseRequestCulture<TStartup>("en-GB", "en-US");
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public InputFormatterTests(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public InputObjectValidationTests(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public InputValidationTests(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public JsonOutputFormatterTests(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public JsonPatchSampleTest(MvcTestFixture<Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public JsonResultTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public LinkGenerationTests(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,24 @@
|
|||
<None Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- For testing the testing infrastructure only -->
|
||||
<WebApplicationFactoryContentRootAttribute
|
||||
Include="BasicWebSite"
|
||||
AssemblyName="BasicWebsite"
|
||||
ContentRootPath="../../../../WebSites/BasicWebSite"
|
||||
ContentRootTest="BasicWebSite.csproj"
|
||||
Priority="-1" />
|
||||
<!-- For testing the testing infrastructure only. This attribute is
|
||||
incorrect by design to ensure that the infrastructure falls back. -->
|
||||
<WebApplicationFactoryContentRootAttribute
|
||||
Include="FiltersWebSite"
|
||||
AssemblyName="FiltersWebSite"
|
||||
ContentRootPath="/../WebSites/FiltersWebSite"
|
||||
ContentRootTest="Incorrect.csproj"
|
||||
Priority="-1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Mvc.Testing\Microsoft.AspNetCore.Mvc.Testing.csproj" />
|
||||
<ProjectReference Include="..\WebSites\ApiExplorerWebSite\ApiExplorerWebSite.csproj" />
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class MvcSandboxTest : IClassFixture<MvcSampleFixture<MvcSandbox.Startup>>
|
||||
public class MvcSandboxTest : IClassFixture<MvcTestFixture<MvcSandbox.Startup>>
|
||||
{
|
||||
public MvcSandboxTest(MvcSampleFixture<MvcSandbox.Startup> fixture)
|
||||
public MvcSandboxTest(MvcTestFixture<MvcSandbox.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public OutputFormatterTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RazorBuildTest(MvcTestFixture<RazorBuildWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public RazorPageExecutionInstrumentationTest(MvcTestFixture<Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -13,9 +15,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RazorPageModelTest(MvcTestFixture<RazorPagesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<RazorPagesWebSite.Startup>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -15,9 +13,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RazorPagesNamespaceTest(MvcTestFixture<RazorPagesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<RazorPagesWebSite.Startup>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using System.Net.Http;
|
|||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -19,9 +20,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public RazorPagesTest(MvcTestFixture<RazorPagesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<RazorPagesWebSite.Startup>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -15,9 +13,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RazorPagesViewSearchTest(MvcTestFixture<RazorPagesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<RazorPagesWebSite.Startup>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RazorPagesWithBasePathTest(MvcTestFixture<RazorPagesWebSite.StartupWithBasePath> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public RazorViewLocationSpecificationTest(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public RemoteAttributeValidationTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -14,9 +16,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RequestFormLimitsTest(MvcTestFixture<BasicWebSite.StartupRequestLimitSize> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<BasicWebSite.StartupRequestLimitSize>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
@ -66,7 +72,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
var result = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task OverrideControllerLevelLimits_UsingDefaultLimits()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RequestServicesTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -23,9 +25,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public RequestSizeLimitTest(MvcTestFixture<BasicWebSite.StartupRequestLimitSize> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<BasicWebSite.StartupRequestLimitSize>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// 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.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
|
|
@ -15,9 +17,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RespectBrowserAcceptHeaderTests(MvcTestFixture<FormatterWebSite.StartupWithRespectBrowserAcceptHeader> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<FormatterWebSite.StartupWithRespectBrowserAcceptHeader>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RouteDataTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public RoutingTests(MvcTestFixture<RoutingWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public SerializableErrorTests(MvcTestFixture<XmlFormattersWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public SimpleTests(MvcTestFixture<SimpleWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public StreamOutputFormatterTest(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public TagHelperComponentTagHelperTest(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public TagHelpersFromServicesTest(MvcTestFixture<ControllersFromServicesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
MvcTestFixture<TagHelpersWebSite.Startup> fixture,
|
||||
MvcEncodedTestFixture<TagHelpersWebSite.Startup> encodedFixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
EncodedClient = encodedFixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
EncodedClient = encodedFixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public TempDataInCookiesTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
protected override HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -20,9 +21,13 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
public TempDataInCookiesUsingCookieConsentTest(
|
||||
MvcTestFixture<BasicWebSite.StartupWithCookieTempDataProviderAndCookieConsent> fixture)
|
||||
{
|
||||
_client = fixture.Client;
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
_client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<BasicWebSite.StartupWithCookieTempDataProviderAndCookieConsent>();
|
||||
|
||||
[Fact]
|
||||
public async Task CookieTempDataProviderCookie_SetInResponse_OnGrantingConsent()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public TempDataInSessionTest(MvcTestFixture<BasicWebSite.StartupWithSessionTempDataProvider> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
protected override HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public TempDataPropertyTest(MvcTestFixture<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,97 @@
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
using System.Threading.Tasks;
|
||||
using BasicWebSite;
|
||||
using BasicWebSite.Controllers;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class TestingInfrastructureTests : IClassFixture<WebApplicationFactory<BasicWebSite.Startup>>
|
||||
{
|
||||
public TestingInfrastructureTests(WebApplicationFactory<BasicWebSite.Startup> fixture)
|
||||
{
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.ConfigureTestServices(s => s.AddSingleton<TestService, OverridenService>());
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task TestingInfrastructure_CanOverrideServiceFromWithinTheTest()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.GetStringAsync("Testing/Builder");
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Test", response);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestingInfrastructure_RedirectHandlerWorksWithPreserveMethod()
|
||||
{
|
||||
// Act
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Testing/RedirectHandler/2")
|
||||
{
|
||||
Content = new ObjectContent<Number>(new Number { Value = 5 }, new JsonMediaTypeFormatter())
|
||||
};
|
||||
request.Headers.Add("X-Pass-Thru", "Some-Value");
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var xPassThruValue = Assert.Single(response.Headers.GetValues("X-Pass-Thru"));
|
||||
Assert.Equal("Some-Value", xPassThruValue);
|
||||
|
||||
var handlerResponse = await response.Content.ReadAsAsync<RedirectHandlerResponse>();
|
||||
Assert.Equal(5, handlerResponse.Url);
|
||||
Assert.Equal(5, handlerResponse.Body);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestingInfrastructure_PostRedirectGetWorksWithCookies()
|
||||
{
|
||||
// Act
|
||||
var acquireToken = await Client.GetAsync("Testing/AntiforgerySimulator/3");
|
||||
Assert.Equal(HttpStatusCode.OK, acquireToken.StatusCode);
|
||||
|
||||
var response = await Client.PostAsync(
|
||||
"Testing/PostRedirectGet/Post/3",
|
||||
content: null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var handlerResponse = await response.Content.ReadAsAsync<PostRedirectGetGetResponse>();
|
||||
Assert.Equal(4, handlerResponse.TempDataValue);
|
||||
Assert.Equal("Value-4", handlerResponse.CookieValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestingInfrastructure_PutWithoutBodyFollowsRedirects()
|
||||
{
|
||||
// Act
|
||||
var response = await Client.PutAsync("Testing/Put/3", content: null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal(5, await response.Content.ReadAsAsync<int>());
|
||||
}
|
||||
|
||||
private class OverridenService : TestService
|
||||
{
|
||||
public OverridenService()
|
||||
{
|
||||
Message = "Test";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,8 +18,8 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
MvcTestFixture<RazorWebSite.Startup> fixture,
|
||||
MvcEncodedTestFixture<RazorWebSite.Startup> encodedFixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
EncodedClient = encodedFixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
EncodedClient = encodedFixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public VersioningTests(MvcTestFixture<VersioningWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public ViewComponentFromServicesTest(MvcTestFixture<ControllersFromServicesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public ViewEngineTests(MvcTestFixture<RazorWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public WebApiCompatShimActionResultTest(MvcTestFixture<WebApiCompatShimWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public WebApiCompatShimActionSelectionTest(MvcTestFixture<WebApiCompatShimWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public WebApiCompatShimBasicTest(MvcTestFixture<WebApiCompatShimWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public WebApiCompatShimParameterBindingTest(MvcTestFixture<WebApiCompatShimWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public XmlDataContractSerializerFormattersWrappingTest(MvcTestFixture<XmlFormattersWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
|
||||
public XmlDataContractSerializerInputFormatterTest(MvcTestFixture<Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public XmlOutputFormatterTests(MvcTestFixture<FormatterWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public XmlSerializerFormattersWrappingTest(MvcTestFixture<XmlFormattersWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
|||
{
|
||||
public XmlSerializerInputFormatterTests(MvcTestFixture<XmlFormattersWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -51,15 +51,18 @@ namespace ApiExplorerWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,15 +38,18 @@ namespace ApplicationModelWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BasicWebSite.Controllers
|
||||
{
|
||||
public class TestingController
|
||||
public class TestingController : Controller
|
||||
{
|
||||
public TestingController(TestService service)
|
||||
{
|
||||
|
|
@ -17,5 +18,94 @@ namespace BasicWebSite.Controllers
|
|||
|
||||
[HttpGet("Testing/Builder")]
|
||||
public string Get() => Service.Message;
|
||||
|
||||
[HttpPost("Testing/RedirectHandler/{value}")]
|
||||
public IActionResult RedirectHandler(
|
||||
[FromRoute]int value,
|
||||
[FromBody] Number number,
|
||||
[FromHeader(Name = "X-Pass-Thru")] string passThruValue)
|
||||
{
|
||||
Response.Headers.Add("X-Pass-Thru", passThruValue);
|
||||
if (value < number.Value)
|
||||
{
|
||||
return RedirectToActionPreserveMethod(
|
||||
nameof(RedirectHandler),
|
||||
"Testing",
|
||||
new { value = value + 1 });
|
||||
}
|
||||
|
||||
return Ok(new RedirectHandlerResponse { Url = value, Body = number.Value });
|
||||
}
|
||||
|
||||
[HttpGet("Testing/AntiforgerySimulator/{value}")]
|
||||
public IActionResult AntiforgerySimulator([FromRoute]int value)
|
||||
{
|
||||
Response.Cookies.Append(
|
||||
"AntiforgerySimulator",
|
||||
$"Cookie-{value.ToString(CultureInfo.InvariantCulture)}");
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
[HttpPost("Testing/PostRedirectGet/Post/{value}")]
|
||||
public IActionResult PostRedirectGetPost([FromRoute]int value)
|
||||
{
|
||||
var compareValue = $"Cookie-{value.ToString(CultureInfo.InvariantCulture)}";
|
||||
if (!Request.Cookies.ContainsKey("AntiforgerySimulator"))
|
||||
{
|
||||
return BadRequest("Missing AntiforgerySimulator cookie");
|
||||
}
|
||||
|
||||
if (!string.Equals(compareValue, Request.Cookies["AntiforgerySimulator"]))
|
||||
{
|
||||
return BadRequest("Values don't match");
|
||||
}
|
||||
|
||||
TempData["Value"] = value + 1;
|
||||
Response.Cookies.Append("Message", $"Value-{(value + 1).ToString(CultureInfo.InvariantCulture)}");
|
||||
|
||||
return RedirectToAction(nameof(PostRedirectGetGet));
|
||||
}
|
||||
|
||||
[HttpGet("Testing/PostRedirectGet/Get/{value}")]
|
||||
public IActionResult PostRedirectGetGet([FromRoute]int value)
|
||||
{
|
||||
return Ok(new PostRedirectGetGetResponse
|
||||
{
|
||||
TempDataValue = (int)TempData["Value"],
|
||||
CookieValue = Request.Cookies["Message"]
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPut("Testing/Put/{value}")]
|
||||
public IActionResult PutNoBody([FromRoute]int value)
|
||||
{
|
||||
if (value < 5)
|
||||
{
|
||||
return RedirectToActionPermanentPreserveMethod(nameof(PutNoBody), "Testing", new { value = value + 1 });
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ok(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PostRedirectGetGetResponse
|
||||
{
|
||||
public int TempDataValue { get; set; }
|
||||
public string CookieValue { get; set; }
|
||||
}
|
||||
|
||||
public class RedirectHandlerResponse
|
||||
{
|
||||
public int Url { get; set; }
|
||||
public int Body { get; set; }
|
||||
}
|
||||
|
||||
public class Number
|
||||
{
|
||||
public int Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,15 +65,18 @@ namespace ControllersFromServicesWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,14 +79,17 @@ namespace CorsWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,15 +24,18 @@ namespace ErrorPageMiddlewareWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ namespace FilesWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string [] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,14 +10,17 @@ namespace FormatterWebSite
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,14 +44,17 @@ namespace HtmlGenerationWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,14 +22,17 @@ namespace RazorBuildWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,15 +44,18 @@ namespace RazorPageExecutionInstrumentationWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,14 +10,17 @@ namespace RazorPagesWebSite
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<StartupWithBasePath>()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<StartupWithBasePath>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,15 +75,18 @@ namespace RazorWebSite
|
|||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration()
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue