mirror of https://github.com/abpframework/abp.git
committed by
GitHub
2 changed files with 163 additions and 5 deletions
@ -0,0 +1,151 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.ApiExplorer; |
|||
using Microsoft.AspNetCore.Mvc.Controllers; |
|||
using Microsoft.AspNetCore.Mvc.Formatters; |
|||
using Microsoft.AspNetCore.Mvc.ModelBinding; |
|||
using Microsoft.AspNetCore.Mvc.Routing; |
|||
using Microsoft.Extensions.Options; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.ApiExploring; |
|||
|
|||
public class AbpRemoteServiceApiDescriptionProvider_Tests |
|||
{ |
|||
private static (AbpRemoteServiceApiDescriptionProvider provider, |
|||
AbpRemoteServiceApiDescriptionProviderOptions options) |
|||
CreateProvider() |
|||
{ |
|||
var options = new AbpRemoteServiceApiDescriptionProviderOptions(); |
|||
options.SupportedResponseTypes.Add(new ApiResponseType |
|||
{ |
|||
Type = typeof(string), |
|||
StatusCode = 400 |
|||
}); |
|||
options.SupportedResponseTypes.Add(new ApiResponseType |
|||
{ |
|||
Type = typeof(string), |
|||
StatusCode = 500 |
|||
}); |
|||
|
|||
var mvcOptions = new MvcOptions(); |
|||
mvcOptions.OutputFormatters.Add(new FakeOutputFormatter()); |
|||
|
|||
var provider = new AbpRemoteServiceApiDescriptionProvider( |
|||
new EmptyModelMetadataProvider(), |
|||
new OptionsWrapper<MvcOptions>(mvcOptions), |
|||
new OptionsWrapper<AbpRemoteServiceApiDescriptionProviderOptions>(options)); |
|||
|
|||
return (provider, options); |
|||
} |
|||
|
|||
private static ApiDescriptionProviderContext CreateContext() |
|||
{ |
|||
var actionDescriptor = new ControllerActionDescriptor |
|||
{ |
|||
ControllerName = "Fake", |
|||
ActionName = "Get", |
|||
ControllerTypeInfo = typeof(FakeRemoteController).GetTypeInfo(), |
|||
MethodInfo = typeof(FakeRemoteController).GetMethod(nameof(FakeRemoteController.Get))!, |
|||
AttributeRouteInfo = new AttributeRouteInfo { Template = "api/fake" } |
|||
}; |
|||
|
|||
var description = new ApiDescription |
|||
{ |
|||
ActionDescriptor = actionDescriptor, |
|||
HttpMethod = "GET", |
|||
RelativePath = "api/fake" |
|||
}; |
|||
|
|||
return new ApiDescriptionProviderContext(new[] { actionDescriptor }) |
|||
{ |
|||
Results = { description } |
|||
}; |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Not_Mutate_Shared_Options_On_Repeated_Calls() |
|||
{ |
|||
var (provider, options) = CreateProvider(); |
|||
|
|||
provider.OnProvidersExecuting(CreateContext()); |
|||
provider.OnProvidersExecuting(CreateContext()); |
|||
provider.OnProvidersExecuting(CreateContext()); |
|||
|
|||
foreach (var template in options.SupportedResponseTypes) |
|||
{ |
|||
template.ApiResponseFormats.ShouldBeEmpty(); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Add_Response_Types_With_Preserved_Template_Fields_And_Formats() |
|||
{ |
|||
var options = new AbpRemoteServiceApiDescriptionProviderOptions(); |
|||
options.SupportedResponseTypes.Add(new ApiResponseType |
|||
{ |
|||
Type = typeof(string), |
|||
StatusCode = 418, |
|||
Description = "I'm a teapot", |
|||
IsDefaultResponse = true |
|||
}); |
|||
|
|||
var mvcOptions = new MvcOptions(); |
|||
mvcOptions.OutputFormatters.Add(new FakeOutputFormatter()); |
|||
|
|||
var provider = new AbpRemoteServiceApiDescriptionProvider( |
|||
new EmptyModelMetadataProvider(), |
|||
new OptionsWrapper<MvcOptions>(mvcOptions), |
|||
new OptionsWrapper<AbpRemoteServiceApiDescriptionProviderOptions>(options)); |
|||
|
|||
var context = CreateContext(); |
|||
provider.OnProvidersExecuting(context); |
|||
|
|||
var result = context.Results.Single(); |
|||
var added = result.SupportedResponseTypes.ShouldHaveSingleItem(); |
|||
added.StatusCode.ShouldBe(418); |
|||
added.Type.ShouldBe(typeof(string)); |
|||
added.Description.ShouldBe("I'm a teapot"); |
|||
added.IsDefaultResponse.ShouldBeTrue(); |
|||
added.ModelMetadata.ShouldNotBeNull(); |
|||
added.ApiResponseFormats.Select(x => x.MediaType) |
|||
.ShouldBe(new[] { "application/json", "text/json" }); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_Not_Throw_Under_Concurrent_Calls() |
|||
{ |
|||
var (provider, _) = CreateProvider(); |
|||
|
|||
var exception = Record.Exception(() => |
|||
Parallel.For(0, 8, _ => |
|||
{ |
|||
for (var i = 0; i < 500; i++) |
|||
{ |
|||
provider.OnProvidersExecuting(CreateContext()); |
|||
} |
|||
})); |
|||
|
|||
exception.ShouldBeNull(); |
|||
} |
|||
|
|||
private sealed class FakeRemoteController : IRemoteService |
|||
{ |
|||
public string Get() => string.Empty; |
|||
} |
|||
|
|||
private sealed class FakeOutputFormatter : IOutputFormatter, IApiResponseTypeMetadataProvider |
|||
{ |
|||
public bool CanWriteResult(OutputFormatterCanWriteContext context) => true; |
|||
|
|||
public Task WriteAsync(OutputFormatterWriteContext context) => Task.CompletedTask; |
|||
|
|||
public IReadOnlyList<string> GetSupportedContentTypes(string? contentType, Type objectType) |
|||
=> new[] { "application/json", "text/json" }; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue