71 votes

Test unitaire ASP.Net MVC Attribut Authorize pour vérifier la redirection vers la page de connexion

Il va probablement s'avérer que j'ai juste besoin d'une autre paire d'yeux. Je dois manquer quelque chose, mais je n'arrive pas à comprendre pourquoi ce genre de chose ne peut pas être testé. J'essaie essentiellement de m'assurer que les utilisateurs non authentifiés ne peuvent pas accéder à la vue en marquant le contrôleur avec l'attribut [Authorize] et j'essaie de tester cela en utilisant le code suivant :

[Fact]
public void ShouldRedirectToLoginForUnauthenticatedUsers()
{
    var mockControllerContext = new Mock<ControllerContext>()
                         { DefaultValue = DefaultValue.Mock };
    var controller = new MyAdminController() 
              {ControllerContext = mockControllerContext.Object};
    mockControllerContext.Setup(c =>
               c.HttpContext.Request.IsAuthenticated).Returns(false);
    var result = controller.Index();
    Assert.IsAssignableFrom<RedirectResult>(result);
}

Le RedirectResult que je recherche est une sorte d'indication que l'utilisateur est redirigé vers le formulaire de connexion, mais au lieu de cela, un ViewResult est toujours renvoyé et lors du débogage, je peux voir que la méthode Index() est frappée avec succès même si l'utilisateur n'est pas authentifié.

Est-ce que je fais quelque chose de mal ? Je teste au mauvais niveau ? Devrais-je plutôt tester au niveau de la route pour ce genre de choses ?

Je sais que l'attribut [Authorize] fonctionne, car lorsque je lance la page, l'écran de connexion m'est effectivement imposé - mais comment puis-je vérifier cela dans un test ?

Le contrôleur et la méthode d'indexation sont très simples, juste pour que je puisse vérifier le comportement. Je les ai inclus par souci d'exhaustivité :

[Authorize]
public class MyAdminController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

Toute aide est appréciée...

0 votes

Une façon de tester ceci est d'utiliser les tests d'intégration en utilisant le serveur hôte en mémoire fourni par Microsoft.AspNetCore.Mvc.Testing, dans lequel vous pouvez simuler AuthHandler. Les détails peuvent être trouvés ici : docs.microsoft.com/en-us/aspnet/core/test/

1voto

Ogglas Points 1

Pour le .NET Framework, nous utilisons cette classe pour vérifier que chaque contrôleur MVC et API dispose d'un système de gestion de la qualité. AuthorizeAttribute et que chaque contrôleur d'API doit avoir un RoutePrefixAttribute .

[TestFixture]
public class TestControllerHasAuthorizeRole
{
    private static IEnumerable<Type> GetChildTypes<T>()
    {
        var types = typeof(Startup).Assembly.GetTypes();
        return types.Where(t => t.IsSubclassOf(typeof(T)) && !t.IsAbstract);
    }

    [Test]
    public void MvcControllersShouldHaveAuthrorizeAttribute()
    {
        var controllers = GetChildTypes<Controller>();
        foreach (var controller in controllers)
        {
            var authorizeAttribute = Attribute.GetCustomAttribute(controller, typeof(System.Web.Mvc.AuthorizeAttribute), true) as System.Web.Mvc.AuthorizeAttribute;
            Assert.IsNotNull(authorizeAttribute, $"MVC-controller {controller.FullName} does not implement AuthorizeAttribute");
        }
    }

    [Test]
    public void ApiControllersShouldHaveAuthorizeAttribute()
    {
        var controllers = GetChildTypes<ApiController>();
        foreach (var controller in controllers)
        {
            var attribute = Attribute.GetCustomAttribute(controller, typeof(System.Web.Http.AuthorizeAttribute), true) as System.Web.Http.AuthorizeAttribute;
            Assert.IsNotNull(attribute, $"API-controller {controller.FullName} does not implement AuthorizeAttribute");
        }
    }

    [Test]
    public void ApiControllersShouldHaveRoutePrefixAttribute()
    {
        var controllers = GetChildTypes<ApiController>();
        foreach (var controller in controllers)
        {
            var attribute = Attribute.GetCustomAttribute(controller, typeof(System.Web.Http.RoutePrefixAttribute), true) as System.Web.Http.RoutePrefixAttribute;
            Assert.IsNotNull(attribute, $"API-controller {controller.FullName} does not implement RoutePrefixAttribute");
            Assert.IsTrue(attribute.Prefix.StartsWith("api/", StringComparison.OrdinalIgnoreCase), $"API-controller {controller.FullName} does not have a route prefix that starts with api/");
        }
    }
}

C'est un peu plus facile dans .NET Core et .NET 5<. Ici un contrôleur MVC hérite de Controller qui, à son tour, hérite de ControllerBase . Un contrôleur d'api hérite directement de ControllerBase et donc nous pouvons tester les contrôleurs MVC et API en utilisant une seule méthode :

public class AuthorizeAttributeTest
{
    private static IEnumerable<Type> GetChildTypes<T>()
    {
        var types = typeof(Startup).Assembly.GetTypes();
        return types.Where(t => t.IsSubclassOf(typeof(T)) && !t.IsAbstract);
    }

    [Fact]
    public void ApiAndMVCControllersShouldHaveAuthorizeAttribute()
    {
        var controllers = GetChildTypes<ControllerBase>();
        foreach (var controller in controllers)
        {
            var attribute = Attribute.GetCustomAttribute(controller, typeof(Microsoft.AspNetCore.Authorization.AuthorizeAttribute), true) as Microsoft.AspNetCore.Authorization.AuthorizeAttribute;
            Assert.NotNull(attribute);
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X