83 lines
3.4 KiB
C#
83 lines
3.4 KiB
C#
using System.Net;
|
|
using MAX.Framework.Conventions;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
|
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
using Microsoft.AspNetCore.Routing;
|
|
using Microsoft.AspNetCore.TestHost;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Store.Users.Tests;
|
|
|
|
/// <summary>验证公共默认 GET 约定的真实路由行为及接口文档。</summary>
|
|
public sealed class DefaultHttpGetTests : IAsyncLifetime
|
|
{
|
|
private WebApplication _app = null!;
|
|
private HttpClient _client = null!;
|
|
|
|
public async Task InitializeAsync()
|
|
{
|
|
var builder = WebApplication.CreateBuilder();
|
|
builder.WebHost.UseTestServer();
|
|
builder.Logging.ClearProviders();
|
|
builder.Services.AddControllers().AddApplicationPart(typeof(DefaultGetTestController).Assembly);
|
|
_app = builder.Build();
|
|
_app.MapControllers();
|
|
await _app.StartAsync();
|
|
_client = _app.GetTestClient();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("Read", "GET", "POST")]
|
|
[InlineData("Create", "POST", "GET")]
|
|
[InlineData("Replace", "PUT", "GET")]
|
|
public async Task UnmarkedAction_DefaultsToGet_AndExplicitMethodsTakePrecedence(string action, string allowed, string rejected)
|
|
{
|
|
using var validRequest = new HttpRequestMessage(new HttpMethod(allowed), $"/default-get-tests/{action}");
|
|
using var validResponse = await _client.SendAsync(validRequest);
|
|
Assert.Equal(HttpStatusCode.OK, validResponse.StatusCode);
|
|
using var invalidRequest = new HttpRequestMessage(new HttpMethod(rejected), $"/default-get-tests/{action}");
|
|
using var invalidResponse = await _client.SendAsync(invalidRequest);
|
|
Assert.Equal(HttpStatusCode.MethodNotAllowed, invalidResponse.StatusCode);
|
|
Assert.Contains(allowed, invalidResponse.Content.Headers.Allow);
|
|
}
|
|
|
|
[Fact]
|
|
public void ActionConstraints_EndpointMetadata_AndApiExplorer_Agree()
|
|
{
|
|
var action = Assert.Single(_app.Services.GetRequiredService<IActionDescriptorCollectionProvider>()
|
|
.ActionDescriptors.Items.OfType<ControllerActionDescriptor>(), a =>
|
|
a.ControllerTypeInfo.AsType() == typeof(DefaultGetTestController) && a.ActionName == "Read");
|
|
Assert.Equal("GET", Assert.Single(Assert.Single(action.ActionConstraints!.OfType<HttpMethodActionConstraint>()).HttpMethods));
|
|
Assert.Equal("GET", Assert.Single(Assert.Single(action.EndpointMetadata.OfType<IHttpMethodMetadata>()).HttpMethods));
|
|
var description = Assert.Single(_app.Services.GetRequiredService<IApiDescriptionGroupCollectionProvider>()
|
|
.ApiDescriptionGroups.Items.SelectMany(g => g.Items), d => d.ActionDescriptor.Id == action.Id);
|
|
Assert.Equal("GET", description.HttpMethod);
|
|
}
|
|
|
|
public async Task DisposeAsync()
|
|
{
|
|
_client?.Dispose();
|
|
if (_app != null) await _app.DisposeAsync();
|
|
}
|
|
}
|
|
|
|
[ApiController]
|
|
[DefaultHttpGet]
|
|
[Route("default-get-tests/[action]")]
|
|
public sealed class DefaultGetTestController : ControllerBase
|
|
{
|
|
public string Read() => "read";
|
|
|
|
[HttpPost]
|
|
public string Create() => "created";
|
|
|
|
[HttpPut]
|
|
public string Replace() => "replaced";
|
|
}
|