public async Task OnActionExecutionAsync_WhenActionDoesNotMatch_BlocksAndReturns_RecaptchaValidationFailedResult()
        {
            // Arrange
            var action      = "submit";
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue);

            _actionExecutingContext.HttpContext = httpContext;

            _recaptchaServiceMock = new Mock <IRecaptchaService>();
            _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null))
            .ReturnsAsync(new ValidationResponse
            {
                Success = true
            })
            .Verifiable();

            _filter        = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger);
            _filter.Action = action;

            // Act
            await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate);

            // Assert
            _recaptchaServiceMock.Verify();
            Assert.IsInstanceOf <IRecaptchaValidationFailedResult>(_actionExecutingContext.Result);
        }
        public async Task TestPostWrongContentType(string httpMethod)
        {
            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()))
            .Verifiable();

            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, loggerFactory);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method      = httpMethod;
            httpContext.Request.ContentType = "Wrong content type";

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never());

            await filter.OnAuthorizationAsync(context);

            Assert.Empty(sink.Scopes);
            Assert.Single(sink.Writes);
            Assert.Equal($"Recaptcha validation failed. The content type is 'Wrong content type', it should be form content.", sink.Writes[0].State?.ToString());
            var httpBadRequest = Assert.IsType <BadRequestResult>(context.Result);

            Assert.Equal(StatusCodes.Status400BadRequest, httpBadRequest.StatusCode);
            Assert.True(context.ModelState.IsValid);
            Assert.Empty(context.ModelState);
        }
示例#3
0
            public async Task VerifyAsyncReturnsBoolean(bool success)
            {
                var reCaptchaServiceMock = new Mock <IReCaptchaService>();

                reCaptchaServiceMock.Setup(x => x.VerifyAsync(It.IsAny <string>())).Returns(Task.FromResult(success));

                var filter = new ValidateRecaptchaFilter(reCaptchaServiceMock.Object, "", "");

                var expected = new StringValues("123");

                var httpContextMock = new Mock <HttpContext>();

                var pageContext = CreatePageContext(new ActionContext(httpContextMock.Object, new RouteData(), new ActionDescriptor()));

                var model = new Mock <PageModel>();

                var pageHandlerExecutedContext = new PageHandlerExecutedContext(
                    pageContext,
                    Array.Empty <IFilterMetadata>(),
                    new HandlerMethodDescriptor(),
                    model.Object);

                var actionExecutingContext = CreatePageHandlerExecutingContext(httpContextMock, pageContext, expected, model);

                PageHandlerExecutionDelegate next = () => Task.FromResult(pageHandlerExecutedContext);

                await filter.OnPageHandlerExecutionAsync(actionExecutingContext, next);

                reCaptchaServiceMock.Verify(x => x.VerifyAsync(It.IsAny <string>()), Times.Once);
            }
        public async Task OnActionExecutionAsync_WhenValidationSuccess_ReturnsOkResult_WithoutAddingResponseToArguments()
        {
            // Arrange
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue);

            _actionExecutingContext.HttpContext = httpContext;

            _recaptchaServiceMock = new Mock <IRecaptchaService>();
            _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null))
            .ReturnsAsync(new ValidationResponse
            {
                Success = true
            })
            .Verifiable();

            _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger);

            // Act
            await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate);

            // Assert
            _recaptchaServiceMock.Verify();
            Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result);
            Assert.AreEqual(0, _actionExecutingContext.ActionArguments.Count);
        }
        public async Task OnActionExecutionAsync_ShouldAddRemoteIp()
        {
            // Arrange
            var ip          = "144.22.5.213";
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue);
            httpContext.Connection.RemoteIpAddress = IPAddress.Parse(ip);

            _actionExecutingContext.HttpContext = httpContext;

            _optionsMock.SetupGet(options => options.CurrentValue)
            .Returns(new RecaptchaOptions {
                UseRemoteIp = true
            });

            _recaptchaServiceMock = new Mock <IRecaptchaService>();
            _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), It.Is <string>(s => s == ip)))
            .ReturnsAsync(new ValidationResponse
            {
                Success = true
            })
            .Verifiable();

            _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger);

            // Act
            await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate);

            // Assert
            _recaptchaServiceMock.Verify();
            Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result);
            Assert.AreEqual(0, _actionExecutingContext.ActionArguments.Count);
        }
        public void InitializeTest()
        {
            _logger = new LoggerFactory().CreateLogger <ValidateRecaptchaFilter>();

            _optionsMock = new Mock <IOptionsMonitor <RecaptchaOptions> >();
            _optionsMock.SetupGet(options => options.CurrentValue)
            .Returns(new RecaptchaOptions());

            _recaptchaServiceMock = new Mock <IRecaptchaService>();
            _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null))
            .ReturnsAsync(new ValidationResponse
            {
                Success = true
            })
            .Verifiable();

            _actionContext = new ActionContext(
                new DefaultHttpContext(),
                Mock.Of <RouteData>(),
                Mock.Of <ActionDescriptor>(),
                new ModelStateDictionary());

            _actionExecutingContext = new ActionExecutingContext(_actionContext, new List <IFilterMetadata>(), new Dictionary <string, object>(), Mock.Of <Controller>())
            {
                Result = new OkResult() // It will return ok unless during code execution you change this when by condition
            };

#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
            _actionExecutionDelegate = async() => { return(new ActionExecutedContext(_actionContext, new List <IFilterMetadata>(), Mock.Of <Controller>())); };
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously

            _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger);
        }
        public async Task TestPostSucessNoIp(string httpMethod)
        {
            var recaptchaResponse = Guid.NewGuid().ToString();

            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(recaptchaResponse, null))
            .Returns(Task.FromResult(0))
            .Verifiable();

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, NullLoggerFactory.Instance);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = httpMethod;
            httpContext.Request.HttpContext.Connection.RemoteIpAddress = null;
            httpContext.Request.ContentType = "application/x-www-form-urlencoded";
            httpContext.Request.Form        = new FormCollection(new Dictionary <string, StringValues>
            {
                { "g-recaptcha-response", recaptchaResponse }
            });

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            await filter.OnAuthorizationAsync(context);

            recaptchaService.Verify();

            Assert.Null(context.Result);
            Assert.True(context.ModelState.IsValid);
            Assert.Empty(context.ModelState);
        }
示例#8
0
        public async Task TestPostFailInvalidResponse(string httpMethod)
        {
            var recaptchaResponse = Guid.NewGuid().ToString();
            var ipAddress         = new IPAddress(new byte[] { 127, 0, 0, 1 });
            var errorMessage      = Guid.NewGuid().ToString();
            var validationMessage = Guid.NewGuid().ToString();

            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(recaptchaResponse, ipAddress.ToString()))
            .Throws(new RecaptchaValidationException(errorMessage, true))
            .Verifiable();

            recaptchaService
            .Setup(a => a.ValidationMessage)
            .Returns(validationMessage)
            .Verifiable();


            var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict);

            configurationService
            .Setup(a => a.Enabled)
            .Returns(true)
            .Verifiable();

            var sink          = new TestSink();
            var loggerFactory = new TestLoggerFactory(sink, enabled: true);

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = httpMethod;
            httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress;
            httpContext.Request.ContentType = "application/x-www-form-urlencoded";
            httpContext.Request.Form        = new FormCollection(new Dictionary <string, StringValues>
            {
                { "g-recaptcha-response", recaptchaResponse }
            });

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            await filter.OnAuthorizationAsync(context);

            recaptchaService.Verify();

            Assert.Empty(sink.Scopes);
            Assert.Single(sink.Writes);
            Assert.Equal($"Recaptcha validation failed. {errorMessage}", sink.Writes[0].State?.ToString());
            Assert.Null(context.Result);
            Assert.False(context.ModelState.IsValid);
            Assert.NotEmpty(context.ModelState);
            Assert.NotNull(context.ModelState["g-recaptcha-response"]);
            Assert.Equal(1, context.ModelState["g-recaptcha-response"].Errors.Count);
            Assert.Equal(validationMessage, context.ModelState["g-recaptcha-response"].Errors.First().ErrorMessage);
        }
示例#9
0
            public async Task VerifyAsyncReturnsBoolean(bool success)
            {
                var reCaptchaServiceMock = new Mock <IReCaptchaService>();

                reCaptchaServiceMock.Setup(x => x.VerifyAsync(It.IsAny <string>())).Returns(Task.FromResult(success));

                var filter = new ValidateRecaptchaFilter(reCaptchaServiceMock.Object, "", "");

                var expected = new StringValues("123");

                var httpContextMock = new Mock <HttpContext>();

                var modelState = new ModelStateDictionary();

                var actionContext = CreateActionContext(httpContextMock, modelState);

                var actionExecutingContext = CreateActionExecutingContext(httpContextMock, actionContext, expected);

                Task <ActionExecutedContext> Next()
                {
                    var ctx = new ActionExecutedContext(actionContext, new List <IFilterMetadata>(), Mock.Of <Controller>());

                    return(Task.FromResult(ctx));
                }

                await filter.OnActionExecutionAsync(actionExecutingContext, Next);

                reCaptchaServiceMock.Verify(x => x.VerifyAsync(It.IsAny <string>()), Times.Once);
                if (!success)
                {
                    Assert.Equal(1, modelState.ErrorCount);
                }
            }
示例#10
0
        public async Task TestPostSkipping(string httpMethod)
        {
            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()))
            .Returns(Task.FromResult(0))
            .Verifiable();

            var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict);

            configurationService
            .Setup(a => a.Enabled)
            .Returns(true)
            .Verifiable();

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, NullLoggerFactory.Instance);

            var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());

            actionContext.HttpContext.Request.Method = httpMethod;

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            await filter.OnAuthorizationAsync(context);

            recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never());

            Assert.Null(context.Result);
            Assert.True(context.ModelState.IsValid);
            Assert.Empty(context.ModelState);
        }
        public async Task TestPostFailMissingResponse(string httpMethod)
        {
            var recaptchaResponse = string.Empty;
            var ipAddress         = new IPAddress(new byte[] { 127, 0, 0, 1 });
            var errorMessage      = Guid.NewGuid().ToString();
            var validationMessage = Guid.NewGuid().ToString();

            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()))
            .Returns(Task.FromResult(0))
            .Verifiable();

            recaptchaService
            .Setup(a => a.ValidationMessage)
            .Returns(validationMessage)
            .Verifiable();

            var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict);

            configurationService
            .Setup(a => a.Enabled)
            .Returns(true)
            .Verifiable();

            var loggerFactory = GetLoggerFactory <ValidateRecaptchaFilter>();

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory.Object);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = httpMethod;
            httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress;
            httpContext.Request.ContentType = "application/x-www-form-urlencoded";
            httpContext.Request.Form        = new FormCollection(new Dictionary <string, StringValues>
            {
                { "g-recaptcha-response", recaptchaResponse }
            });

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            await filter.OnAuthorizationAsync(context);

            recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never());

            Assert.Null(context.Result);
            Assert.False(context.ModelState.IsValid);
            Assert.NotEmpty(context.ModelState);
            Assert.NotNull(context.ModelState["g-recaptcha-response"]);
            Assert.Equal(1, context.ModelState["g-recaptcha-response"].Errors.Count);
            Assert.Equal(validationMessage, context.ModelState["g-recaptcha-response"].Errors.First().ErrorMessage);
        }
        public void Construction_IsSuccessful()
        {
            // Arrange


            // Act
            var instance = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger);

            // Assert
            Assert.NotNull(instance);
        }
        public ValidateRecaptchaFilterTests()
        {
            _stubVerifySite = new Mock <ISiteVerifier>();
            var options = new ValidateRecaptchaFilterOptions
            {
                ErrorMessage = ErrorMessage,
                HostName     = HostName
            };

            _filter  = new ValidateRecaptchaFilter(_stubVerifySite.Object, options);
            _context = CreateContext();
        }
示例#14
0
        public async Task TestPostFail(string httpMethod)
        {
            var recaptchaResponse = Guid.NewGuid().ToString();
            var ipAddress         = new IPAddress(new byte[] { 127, 0, 0, 1 });
            var errorMessage      = Guid.NewGuid().ToString();

            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(recaptchaResponse, ipAddress.ToString()))
            .Throws(new RecaptchaValidationException(errorMessage, false))
            .Verifiable();

            var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict);

            configurationService
            .Setup(a => a.Enabled)
            .Returns(true)
            .Verifiable();

            var logger        = new TestLogger();
            var loggerFactory = new TestLoggerFactory <ValidateRecaptchaFilter>(logger);

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = httpMethod;
            httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress;
            httpContext.Request.ContentType = "application/x-www-form-urlencoded";
            httpContext.Request.Form        = new FormCollection(new Dictionary <string, StringValues>
            {
                { "g-recaptcha-response", recaptchaResponse }
            });

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            await filter.OnAuthorizationAsync(context);

            recaptchaService.Verify();

            Assert.Equal(0, logger.ScopeCount);
            Assert.Single(logger.Log);
            Assert.Equal($"Recaptcha validation failed. {errorMessage}", logger.Log[0]);
            var httpBadRequest = Assert.IsType <BadRequestResult>(context.Result);

            Assert.Equal(StatusCodes.Status400BadRequest, httpBadRequest.StatusCode);
            Assert.True(context.ModelState.IsValid);
            Assert.Empty(context.ModelState);
        }
        public async Task OnActionExecutionAsync_WhenActionDoesNotMatch_ContinuesAndAddsResponseToArguments()
        {
            // Arrange
            var action      = "submit";
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue);

            _actionExecutingContext.HttpContext = httpContext;

            _recaptchaServiceMock = new Mock <IRecaptchaService>();
            _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null))
            .ReturnsAsync(new ValidationResponse
            {
                Success       = true,
                ErrorMessages = new List <string> {
                    "invalid-input-response"
                }
            })
            .Verifiable();

            _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger)
            {
                OnValidationFailedAction = ValidationFailedAction.ContinueRequest,
                Action = action
            };

            _actionExecutingContext.ActionArguments.Add("argumentName", new ValidationResponse {
                Success = true
            });

            // Act
            await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate);

            // Assert
            _recaptchaServiceMock.Verify();
            Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result);
            Assert.IsTrue((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Success);
            Assert.GreaterOrEqual((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Errors.Count(), 1);
            Assert.AreEqual(ValidationError.InvalidInputResponse, (_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Errors.First());
        }
        public async Task OnActionExecutionAsync_WhenValidationSuccess_ContinuesAndAddsResponseToArguments()
        {
            // Arrange
            var action      = "submit";
            var httpContext = new DefaultHttpContext();

            httpContext.Request.Headers.Add(RecaptchaServiceConstants.TokenKeyName, TokenValue);

            _actionExecutingContext.HttpContext = httpContext;

            _recaptchaServiceMock = new Mock <IRecaptchaService>();
            _recaptchaServiceMock.Setup(service => service.ValidateRecaptchaResponse(It.Is <string>(s => s == TokenValue), null))
            .ReturnsAsync(new ValidationResponse
            {
                Success = true,
                Action  = action
            })
            .Verifiable();

            _filter = new ValidateRecaptchaFilter(_recaptchaServiceMock.Object, _optionsMock.Object, _logger)
            {
                Action = action
            };

            _actionExecutingContext.ActionArguments.Add("argumentName", new ValidationResponse {
                Success = false, Action = string.Empty
            });

            // Act
            await _filter.OnActionExecutionAsync(_actionExecutingContext, _actionExecutionDelegate);

            // Assert
            _recaptchaServiceMock.Verify();
            Assert.IsInstanceOf <OkResult>(_actionExecutingContext.Result);
            Assert.IsTrue((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Success);
            Assert.AreEqual(action, (_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Action);
            Assert.AreEqual((_actionExecutingContext.ActionArguments["argumentName"] as ValidationResponse).Errors.Count(), 0);
        }
        public async Task TestPostWrongContentType(string httpMethod)
        {
            var recaptchaService = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            recaptchaService
            .Setup(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()))
            .Verifiable();

            var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict);

            configurationService
            .Setup(a => a.Enabled)
            .Returns(true)
            .Verifiable();

            var loggerFactory = GetLoggerFactory <ValidateRecaptchaFilter>();

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory.Object);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method      = httpMethod;
            httpContext.Request.ContentType = "Wrong content type";

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            recaptchaService.Verify(a => a.ValidateResponseAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never());

            await filter.OnAuthorizationAsync(context);

            var httpBadRequest = Assert.IsType <BadRequestResult>(context.Result);

            Assert.Equal(StatusCodes.Status400BadRequest, httpBadRequest.StatusCode);
            Assert.True(context.ModelState.IsValid);
            Assert.Empty(context.ModelState);
        }
        public async Task DoNotValidateIfDisabled()
        {
            var recaptchaResponse = string.Empty;
            var ipAddress         = new IPAddress(new byte[] { 127, 0, 0, 1 });
            var recaptchaService  = new Mock <IRecaptchaValidationService>(MockBehavior.Strict);

            var configurationService = new Mock <IRecaptchaConfigurationService>(MockBehavior.Strict);

            configurationService
            .Setup(a => a.Enabled)
            .Returns(false)
            .Verifiable();

            var loggerFactory = GetLoggerFactory <ValidateRecaptchaFilter>();

            var filter = new ValidateRecaptchaFilter(recaptchaService.Object, configurationService.Object, loggerFactory.Object);

            var httpContext = new DefaultHttpContext();

            httpContext.Request.Method = "POST";
            httpContext.Request.HttpContext.Connection.RemoteIpAddress = ipAddress;
            httpContext.Request.ContentType = "application/x-www-form-urlencoded";
            httpContext.Request.Form        = new FormCollection(new Dictionary <string, StringValues>
            {
                { "g-recaptcha-response", recaptchaResponse }
            });

            var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

            var context = new AuthorizationFilterContext(actionContext, new[] { filter });

            await filter.OnAuthorizationAsync(context);

            Assert.Null(context.Result);

            configurationService.Verify();
            recaptchaService.Verify();
        }