简体   繁体   English

如何对Web API 2的防伪令牌过滤器进行单元测试

[英]How to unit test AntiforgeryToken filter for web api 2

I am trying to write unit test case using MsTest for custom filter which has the logic to validate the Antiforgerytoken for POST method in ASP.NET WEB API 2 project. 我正在尝试使用MsTest编写用于自定义过滤器的单元测试用例,该过滤器具有验证ASP.NET WEB API 2项目中POST方法的Antiforgerytoken的逻辑。

[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        try
        {

            string cookieToken = null;
            string formToken = null;

            if (actionContext.Request.IsAjaxRequest())
            {
                IEnumerable<string> tokenHeaders;
                if (actionContext.Request.Headers.TryGetValues("__RequestVerificationToken", out tokenHeaders))
                {
                    string[] tokens = tokenHeaders.First().Split(':');
                    if (tokens.Length == 2)
                    {
                        cookieToken = tokens[0].Trim();
                        formToken = tokens[1].Trim();
                    }
                }
                if (cookieToken != null && formToken !=null)
                {
                    AntiForgery.Validate(cookieToken, formToken);
                }
                else
                {
                    AntiForgery.Validate();
                }                    
            }

        }
        catch (Exception ex)
        {
            ErrorSignal.FromCurrentContext().Raise(ex);
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
        }            
    }
}

In the below code IsAjaxRequest is an extension method 在下面的代码中, IsAjaxRequest是一种扩展方法

public static class HttpRequestMessageExtensions
{
    public static bool IsAjaxRequest(this HttpRequestMessage request)
    {
        IEnumerable<string> headers;
        if (request.Headers.TryGetValues("X-Requested-With", out headers))
        {
            var header = headers.FirstOrDefault();
            if (!string.IsNullOrWhiteSpace(header))
            {
                return header.ToLowerInvariant() == "xmlhttprequest";
            }
        }

        return false;
    }
}

Here my issue how to mock the IsAjaxRequest and how to pass actionContext parameter to the OnActionExecuting method. 在这里,我的问题是如何模拟IsAjaxRequest以及如何将actionContext参数传递给OnActionExecuting方法。

Can anyone help me to provide some code samples regarding this? 谁能帮助我提供一些与此相关的代码示例?

IsAjaxRequest is an extension method which mean it is a static method. IsAjaxRequest是扩展方法,这意味着它是静态方法。

You shouldn't mock static methods. 您不应该模拟静态方法。 You should test it as a part of your method under test behavior. 您应该将其作为测试行为的一部分进行测试。

The following example shows how to test invalid request:(I removed the :: ErrorSignal.FromCurrentContext().Raise(ex); since I didn't know which assembly to add... so add the missing assert\\s in your test...) 下面的示例显示了如何测试无效请求:(我删除了ErrorSignal.FromCurrentContext().Raise(ex);因为我不知道要添加哪个程序集...因此在测试中添加缺少的assert \\ s ...)

[TestMethod]
public void TestMethod1()
{
    var target = new ValidateJsonAntiForgeryTokenAttribute();
    var requestMessage = new HttpRequestMessage();
    requestMessage.Headers.Add("X-Requested-With", new[] {"xmlhttprequest"});
    var fakeDescriptor = new Mock<HttpActionDescriptor>();
    var controllerContext = new HttpControllerContext {Request = requestMessage};
    var context = new HttpActionContext(controllerContext, fakeDescriptor.Object);


    target.OnActionExecuting(context);


    Assert.AreEqual(HttpStatusCode.Forbidden, actionContext.Response.StatusCode);
}

You can mock the static method if you really need to. 如果确实需要,可以模拟静态方法。 There's my example of the test with Typemock isolator: 这是我使用Typemock隔离器进行测试的示例:

[TestMethod, Isolated]
public void TestValidate()
{
    //How to fake action context to further passing it as a parameter:
    var fake = Isolate.Fake.AllInstances<HttpActionContext>();
    Isolate.Fake.StaticMethods<HttpActionContext>();

    //How to mock IsAjaxRequset:
    var request = new HttpRequestMessage();
    Isolate.WhenCalled(() => request.IsAjaxRequest()).WillReturn(true);            

    //Arrange:
    ValidateJsonAntiForgeryTokenAttribute target = new ValidateJsonAntiForgeryTokenAttribute();
    Isolate.WhenCalled(() => AntiForgery.Validate()).IgnoreCall();

    //Act:
    target.OnActionExecuting(fake);

    //Assert:
    Isolate.Verify.WasCalledWithAnyArguments(() => AntiForgery.Validate());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM