c # WebApi, как выполнить модульное тестирование, если действие контроллера украшено атрибутом авторизации с конкретными аргументами - PullRequest
0 голосов
/ 29 марта 2019

У нас есть пользовательский AuthorizationFilterAttribute для оформления действий контроллера WebApi, который принимает параметр enum для определения уровня доступа.

public enum AuthLevel
{
    Any = 1,
    Client = 2,
    Server = 4
}

[AttributeUsage(AttributeTargets.Method)]
public class CustomAuthorizeAttribute : AuthorizationFilterAttribute
{
    private readonly AuthLevel _authLevel;

    public CustomAuthorizeAttribute(AuthLevel authLevel)
    {
        _authLevel = authLevel;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        ...
    }
}

Использование:

public class TestController : ApiController
{
    [HttpGet, Route("api/test")]
    [CustomAuthorizeAttribute(AuthLevel.Client)]
    public IHttpActionResult Get()
    {
        return Ok();
    }

    [HttpGet, Route("api/testasync")]
    [CustomAuthorizeAttribute(AuthLevel.Server)]
    public async Task<IHttpActionResult> GetAsync()
    {
        return Task.FromResult(Ok());
    }
}

Пока нетВ качестве замены хороших интеграционных тестов, я хотел бы иметь возможность модульного тестирования, чтобы этот атрибут был определен в действии контроллера с правильным значением перечисления.Он также должен работать как со стандартными, так и с асинхронными методами.

1 Ответ

0 голосов
/ 29 марта 2019

Для этого я создал несколько методов расширения:

public static bool HasExpectedAuthLevel<T>(this T controller, Expression<Action<T>> action, AuthLevel expectedAuthLevel)
    where T : ApiController
{
    return controller.HasAttributeWithExpectedArgument(action, typeof(CustomAuthorizeAttribute), expectedAuthLevel);
}

public static bool HasExpectedAuthLevel<T>(this T controller, Expression<Func<T, Task>> action, AuthLevel expectedAuthLevel)
    where T : ApiController
{
    return controller.HasAttributeWithExpectedArgument(action, typeof(CustomAuthorizeAttribute), expectedAuthLevel);
}

public static bool HasAttributeWithExpectedArgument<TController, TArgument>(this TController controller, Expression<Action<TController>> action, Type attributeType, TArgument expectedArgument)
    where TController : ApiController
{
    return HasAttributeWithExpectedArgument(action?.Body as MethodCallExpression, attributeType, expectedArgument);
}

public static bool HasAttributeWithExpectedArgument<TController, TArgument>(this TController controller, Expression<Func<TController, Task>> action, Type attributeType, TArgument expectedArgument)
    where TController : ApiController
{
    return HasAttributeWithExpectedArgument(action?.Body as MethodCallExpression, attributeType, expectedArgument);
}

private static bool HasAttributeWithExpectedArgument<TArgument>(MethodCallExpression action, Type attributeType, TArgument expectedArgument)
{
    if (action == null || !attributeType.IsSubclassOf(typeof(Attribute)))
    {
        return false;
    }

    var attributesData = action.Method.GetCustomAttributesData().Where(a => a.AttributeType == attributeType).ToArray();

    return attributesData.Any(attribute =>
        attribute.ConstructorArguments.Any(arg =>
            arg.ArgumentType == typeof(TArgument) && EqualityComparer<TArgument>.Default.Equals((TArgument)arg.Value, expectedArgument)));
}

Использование:

[Test]
public void Get_HasCorrectAuthLevel()
{
    var controller = new TestController();
    controller.HasExpectedAuthLevel(c => c.Get(), AuthLevel.Client).Should().BeTrue();
    controller.HasExpectedAuthLevel(c => c.GetAsync(), AuthLevel.Server).Should().BeTrue();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...