using System; using System.Security.Claims; using System.Threading.Tasks; using AMWD.Common.AspNetCore.Security.PathProtection; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; namespace UnitTests.AspNetCore.Security.PathProtection { [TestClass] [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] public class ProtectedPathMiddlewareTests { private Mock nextMock; private Mock httpContextMock; private Mock authorizationServiceMock; private Mock authenticationServiceMock; private ProtectedPathOptions options; [TestInitialize] public void InitializeTest() { options = new ProtectedPathOptions { Path = "/secure/protected", PolicyName = "Protection" }; } [TestMethod] public async Task ShouldValidateAccessSuccessful() { // arrange var middleware = GetMiddleware(); var context = GetHttpContext(options.Path); var auth = GetAuthService(true); // act await middleware.InvokeAsync(context, auth); // assert authorizationServiceMock.Verify(s => s.AuthorizeAsync(It.IsAny(), It.IsAny(), options.PolicyName), Times.Once); authorizationServiceMock.VerifyNoOtherCalls(); authenticationServiceMock.Verify(s => s.ChallengeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); authenticationServiceMock.VerifyNoOtherCalls(); nextMock.Verify(n => n.Invoke(It.IsAny()), Times.Once); nextMock.VerifyNoOtherCalls(); } [TestMethod] public async Task ShouldNotValidate() { // arrange var middleware = GetMiddleware(); var context = GetHttpContext("/some/path"); var auth = GetAuthService(true); // act await middleware.InvokeAsync(context, auth); // assert authorizationServiceMock.Verify(s => s.AuthorizeAsync(It.IsAny(), It.IsAny(), options.PolicyName), Times.Never); authorizationServiceMock.VerifyNoOtherCalls(); authenticationServiceMock.Verify(s => s.ChallengeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); authenticationServiceMock.VerifyNoOtherCalls(); nextMock.Verify(n => n.Invoke(It.IsAny()), Times.Once); nextMock.VerifyNoOtherCalls(); } [TestMethod] public async Task ShouldValidateAccessFailure() { // arrange var middleware = GetMiddleware(); var context = GetHttpContext(options.Path); var auth = GetAuthService(false); // act await middleware.InvokeAsync(context, auth); // assert authorizationServiceMock.Verify(s => s.AuthorizeAsync(It.IsAny(), It.IsAny(), options.PolicyName), Times.Once); authorizationServiceMock.VerifyNoOtherCalls(); authenticationServiceMock.Verify(s => s.ChallengeAsync(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); authenticationServiceMock.VerifyNoOtherCalls(); nextMock.Verify(n => n.Invoke(It.IsAny()), Times.Never); nextMock.VerifyNoOtherCalls(); } private ProtectedPathMiddleware GetMiddleware() { nextMock = new Mock(); return new ProtectedPathMiddleware(nextMock.Object, options); } private HttpContext GetHttpContext(string requestPath) { var requestMock = new Mock(); requestMock .Setup(r => r.Path) .Returns(new PathString(requestPath)); authenticationServiceMock = new Mock(); var requestServicesMock = new Mock(); requestServicesMock .Setup(s => s.GetService(typeof(IAuthenticationService))) .Returns(authenticationServiceMock.Object); httpContextMock = new Mock(); httpContextMock .Setup(c => c.Request) .Returns(requestMock.Object); httpContextMock .Setup(c => c.RequestServices) .Returns(requestServicesMock.Object); return httpContextMock.Object; } private IAuthorizationService GetAuthService(bool success) { authorizationServiceMock = new Mock(); authorizationServiceMock .Setup(service => service.AuthorizeAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(() => success ? AuthorizationResult.Success() : AuthorizationResult.Failed()); return authorizationServiceMock.Object; } } }