|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Authorization;
[assembly: ProducesErrorResponseType(typeof(InvalidEnumArgumentException))]
namespace Microsoft.AspNetCore.Mvc.ApplicationModels;
public class ApiConventionApplicationModelConventionTest
{
[Fact]
public void Apply_DoesNotAddConventionItem_IfNoConventionMatches()
{
// Arrange
var actionModel = GetActionModel(nameof(TestController.NoMatch));
var convention = GetConvention();
// Act
convention.Apply(actionModel);
// Assert
Assert.DoesNotContain(typeof(ApiConventionResult), actionModel.Properties.Keys);
}
[Fact]
public void Apply_AddsConventionItem_IfConventionMatches()
{
// Arrange
var actionModel = GetActionModel(nameof(TestController.Delete));
var convention = GetConvention();
// Act
convention.Apply(actionModel);
// Assert
var value = actionModel.Properties[typeof(ApiConventionResult)];
Assert.NotNull(value);
}
[Fact]
public void Apply_AddsConventionItem_IfActionHasNonConventionBasedFilters()
{
// Arrange
var actionModel = GetActionModel(nameof(TestController.Delete));
actionModel.Filters.Add(new AuthorizeFilter());
var convention = GetConvention();
// Act
convention.Apply(actionModel);
// Assert
var value = actionModel.Properties[typeof(ApiConventionResult)];
Assert.NotNull(value);
}
[Fact]
public void Apply_UsesDefaultErrorType_IfActionHasNoAttributes()
{
// Arrange
var expected = typeof(InvalidFilterCriteriaException);
var controller = new ControllerModel(typeof(object).GetTypeInfo(), Array.Empty<object>());
var action = new ActionModel(typeof(object).GetMethods()[0], Array.Empty<object>())
{
Controller = controller,
};
var convention = GetConvention(expected);
// Act
convention.Apply(action);
// Assert
var attribute = GetProperty<ProducesErrorResponseTypeAttribute>(action);
Assert.Equal(expected, attribute.Type);
}
[Fact]
public void Apply_UsesValueFromProducesErrorResponseTypeAttribute_SpecifiedOnControllerAsssembly()
{
// Arrange
var expected = typeof(InvalidEnumArgumentException);
var action = GetActionModel(nameof(TestController.Delete));
var convention = GetConvention();
// Act
convention.Apply(action);
// Assert
var attribute = GetProperty<ProducesErrorResponseTypeAttribute>(action);
Assert.Equal(expected, attribute.Type);
}
[Fact]
public void Apply_UsesValueFromProducesErrorResponseTypeAttribute_SpecifiedOnController()
{
// Arrange
var expected = typeof(InvalidTimeZoneException);
var action = GetActionModel(
nameof(TestController.Delete),
controllerAttributes: new[] { new ProducesErrorResponseTypeAttribute(expected) });
var convention = GetConvention();
// Act
convention.Apply(action);
// Assert
var attribute = GetProperty<ProducesErrorResponseTypeAttribute>(action);
Assert.Equal(expected, attribute.Type);
}
[Fact]
public void Apply_UsesValueFromProducesErrorResponseTypeAttribute_SpecifiedOnAction()
{
// Arrange
var expected = typeof(InvalidTimeZoneException);
var action = GetActionModel(
nameof(TestController.Delete),
actionAttributes: new[] { new ProducesErrorResponseTypeAttribute(expected) },
controllerAttributes: new[] { new ProducesErrorResponseTypeAttribute(typeof(Guid)) });
var convention = GetConvention();
// Act
convention.Apply(action);
// Assert
var attribute = GetProperty<ProducesErrorResponseTypeAttribute>(action);
Assert.Equal(expected, attribute.Type);
}
[Fact]
public void Apply_AllowsVoidsErrorType()
{
// Arrange
var expected = typeof(void);
var action = GetActionModel(nameof(TestController.Delete), new[] { new ProducesErrorResponseTypeAttribute(expected) });
var convention = GetConvention();
// Act
convention.Apply(action);
// Assert
var attribute = GetProperty<ProducesErrorResponseTypeAttribute>(action);
Assert.Equal(expected, attribute.Type);
}
private ApiConventionApplicationModelConvention GetConvention(Type errorType = null)
{
errorType = errorType ?? typeof(ProblemDetails);
return new ApiConventionApplicationModelConvention(new ProducesErrorResponseTypeAttribute(errorType));
}
private static TValue GetProperty<TValue>(ActionModel action)
{
return Assert.IsType<TValue>(action.Properties[typeof(TValue)]);
}
private static ActionModel GetActionModel(
string actionName,
object[] actionAttributes = null,
object[] controllerAttributes = null)
{
actionAttributes = actionAttributes ?? Array.Empty<object>();
controllerAttributes = controllerAttributes ?? new[] { new ApiConventionTypeAttribute(typeof(DefaultApiConventions)) };
var controllerModel = new ControllerModel(typeof(TestController).GetTypeInfo(), controllerAttributes);
var actionModel = new ActionModel(typeof(TestController).GetMethod(actionName), actionAttributes)
{
Controller = controllerModel,
};
controllerModel.Actions.Add(actionModel);
return actionModel;
}
private class TestController
{
public IActionResult NoMatch() => null;
public IActionResult Delete(int id) => null;
}
}
|