Test de l’utilisateur s’il dispose d’une autorité spécifique utilisant AuthorizeAsync () dans Xunit-Unit Testing

La question a été mise à jour pour une meilleure explication du problème que j’ai,

J’ai simplement ce contrôleur,

[Authorize] public class IdeaManagementController : Controller { private IIdeaManagementService _ideaManagementService; private ITenantService _tenantService; private ITagService _tagService; private IEmployeeIdeaCategoryService _ideaManagementCategoryService; private static PbdModule _modul = PbdModule.IdeaManagement; IAuthorizationService _authorizationService; public IdeaManagementController( IIdeaManagementService ideaManagementService, ITenantService tenantService, ITagService tagService, IAuthorizationService authorizationService, IEmployeeIdeaCategoryService ideaManagementCategoryService) { _ideaManagementService = ideaManagementService; _tenantService = tenantService; _tagService = tagService; _authorizationService = authorizationService; _ideaManagementCategoryService = ideaManagementCategoryService; } public async Task IdeaCoordinator() { if (!await _authorizationService.AuthorizeAsync(User, "IdeaManagement_Coordinator")) { return new ChallengeResult(); } var ideas = _ideaManagementService.GetByIdeaCoordinator(_tenantService.GetCurrentTenantId()); return View(ideas); } } 

et j’ai simplement besoin de tester la vue rétrécie viewResult de la méthode d’action IdeaCoordinator mais je ne pouvais pas simplement parce que si la méthode de validation _authorizationService.AuthorizeAsync, j’essayais de me moquer de la méthode, mais simplement parce que c’était une méthode d’extension , puis j’ai essayé de créer une solution de contournement en créant une nouvelle interface qui implémentait IAuthorizationService et Mock qui personnalisait cette interface

 public interface ICustomAuthorizationService : IAuthorizationService { Task AuthorizeAsync(ClaimsPrincipal user, ssortingng policyName); } public IAuthorizationService CustomAuthorizationServiceFactory() { Mock _custom = new Mock(); _custom.Setup(c => c.AuthorizeAsync(It.IsAny(), "IdeaManagement_Coordinator")).ReturnsAsync(true); return _custom.Object; } 

et Injectez-le pendant que j’appelle le constructeur du contrôleur, puis je me suis retrouvé comme ça:

 [Theory] [InlineData(1)] public async void IdeaManager_Should_Return_ViewResult(int _currentTenanatID) { // Arrange .. _IdeaManagementControllerObject = new IdeaManagementController (IdeaManagementServiceMockFactory(_currentTenanatID), TenantServiceMockFactory(_currentTenanatID), TagServiceMockFactory(), AuthorizationServiceMockFactory(), EmployeeIdeaCategoryServiceMockFactory()); // Act var _view = await _IdeaManagementControllerObject.IdeaCoordinator() as ViewResult; // Assert Assert.IsType(new ViewResult().GetType(), _view); } 

Je m’attendais à des résultats différents, car j’avais indiqué que le résultat renvoyé était true pour ignorer cette ligne de code et continuer jusqu’à Viewresult. Cependant, alors que je déboguais ma méthode de test, le compilateur a intégré le message de validation car il ne ressentait pas les modifications apscopes. sur le résultat de la méthode AuthorizeAsync .. entrez la description de l'image ici

Merci d’avance.

== Solution ==

Intro:

«Nous ne pouvons pas résoudre nos problèmes avec le même niveau de pensée qui les a créés» – Albert Einstein. et avec cette adorable adage, je voudrais informer que j’ai passé environ une semaine à résoudre ce problème jusqu’à ce que j’ai le sentiment qu’il ne sera jamais résolu à ce moment-là, j’ai passé des heures à enquêter, mais après avoir lu un article et après avoir changé de façon de penser, la solution est venue dans 30 minutes.

Problème en un coup d’œil:

J’essayais simplement de tester la méthode d’action écrite ci-dessus, et j’ai un grave problème à ne pas pouvoir me moquer de la méthode “AuthorizeAsync” et tout simplement parce que c’est une méthode d’extension intégrée et en raison de la nature de la méthode d’extension méthode statique, on ne peut jamais se moquer de la manière traditionnelle de se moquer des classes.

Solution en détails:

Pour pouvoir me moquer de cette méthode d’action, j’ai créé une classe statique qui contient des delegates statiques. Avec ces delegates, je vais me moquer ou, comme on peut le dire, “envelopper” ma méthode d’extension en remplaçant mes delegates statiques dans ma classe de test d’unité comme suit .

 public static class DelegateFactory { public static Func<ClaimsPrincipal, object, string, Task> AuthorizeAsync = (c, o, s) => { return AuthorizationServiceExtensions.AuthorizeAsync(null, null, ""); }; } public Mock AuthorizationServiceMockExtensionFactory() { var mockRepository = new Moq.MockRepository(Moq.MockBehavior.Ssortingct); var mockFactory = mockRepository.Create(); var ClaimsPrincipal = mockRepository.Create(); mockFactory.Setup(x => x.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(true); return mockFactory; } 

et lors de ma méthode de test, je viens d’appeler l’object simulé dans l’instanciation du constructeur du contrôleur.

  [Fact] public async void IdeaCoordinator_When_AuthroizedUser_IsNotNull_But_IdeaManagement_Manager_Authorized_Return_View() { // Arrange int approvedByID = data.GetTenantByID(1).TenantId; _IdeaManagementControllerObject = new IdeaManagementController (IdeaManagementServiceMockFactory().Object, TenantServiceMockFactory().Object, TagServiceMockFactory().Object, AuthorizationServiceMockExtensionFactory().Object, EmployeeIdeaCategoryServiceMockFactory().Object); //Act IdeaManagementServiceMockFactory().Setup(m => m.GetByIdeaCoordinator(approvedByID)).Returns(data.GetCordinatedEmpIdeas(approvedByID)); ViewResult _view = await _IdeaManagementControllerObject.IdeaCoordinator() as ViewResult; var model = _view.Model as List; // Assert Assert.Equal(3, model.Count); Assert.IsType(new ViewResult().GetType(), _view); } 

et comme il est dit, la plus grande cause du bonheur est la gratitude.J’aimerais remercier Stephen Fuqua pour sa shinye solution et son article, http://www.safnet.com/writing/tech/2014/04/making-mockery- of-extension-methods.html

Merci tout le monde 🙂 !

Mock les dépendances nécessaires pour le test. La méthode testée utilise IAuthorizationService , IIdeaManagementService et ITenantService . Tout le rest n’est pas nécessaire pour ce test particulier.

Coupler votre code à un code tiers que vous ne possédez pas et que vous ne contrôlez pas, il est difficile de le tester. Ma suggestion est de résumer le fait que derrière une interface que vous contrôlez, vous avez cette flexibilité. Alors changez IAuthorizationService pour votre propre abstraction.

 public interface ICustomAuthorizationService { Task AuthorizeAsync(ClaimsPrincipal user, ssortingng policyName); } 

L’implémentation encapsulerait le service d’autorisation réel qui utilise la méthode d’extension

 public class CustomAuthorizationService: ICustomAuthorizationService { private readonly IAuthorizationService service; public CustomAuthorizationService(IAuthorizationService service) { this.service = service; } public Task AuthorizeAsync(ClaimsPrincipal user, ssortingng policyName) { return service.AuthorizeAsync(user, policyName); } } 

Assurez-vous d’enregistrer votre emballage. par exemple.

 services.AddSingleton(); 

Si Identity est déjà ajouté à la collection de services, IAuthorizationService sera injecté dans votre service personnalisé une fois résolu.

Alors maintenant, pour votre test, vous pouvez vous moquer des interfaces que vous contrôlez et ne pas avoir à vous soucier de casser du code tiers.

 [Theory] [InlineData(1)] public async void IdeaManager_Should_Return_ViewResult(int _currentTenanatID) { // Arrange .. var ideaManagementService = new Mock(); var tenantService = new Mock(); var authorizationService = new Mock(); var sut = new IdeaManagementController( ideaManagementService.Object, tenantService.Object, null, authorizationService.Object, null); authorizationService .Setup(_ => _.AuthorizeAsync(It.IsAny(), "IdeaManagement_Coordinator")) .ReturnsAsync(true); tenantService .Setup(_ => _.GetCurrentTenantId()) .Returns(_currentTenanatID); var ideas = new //{what ever is your expected return type here} ideaManagementService .Setup(_ => _.GetByIdeaCoordinator(_currentTenanatID)) .Returns(ideas); // Act var _view = await sut.IdeaCoordinator() as ViewResult; // Assert Assert.IsNotNull(_view); Assert.IsType(typeof(ViewResult), _view); Assert.AreEqual(ideas, view.Model); } 

Ceci est un exemple des inconvénients des méthodes d’extension car elles sont statiques et difficiles à tester si elles cachent des dépendances.