如何对 Web API 2 的防伪令牌筛选器进行单元测试
本文关键字:筛选 令牌 单元测试 Web API | 更新日期: 2023-09-27 18:32:59
我正在尝试使用自定义过滤器的MsTest编写单元测试用例,该过滤器具有在WEB API 2项目中验证POST方法Antiforgerytoken
ASP.NET 逻辑。
[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);
}
}
}
在下面的代码中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;
}
}
在这里,我的问题是如何模拟IsAjaxRequest
以及如何actionContext
参数传递给OnActionExecuting
方法。
谁能帮我提供一些关于此的代码示例?
IsAjaxRequest
是一个扩展方法,这意味着它是一个静态方法。
你不应该嘲笑静态方法。应将其作为受测方法行为的一部分进行测试。
以下示例显示了如何测试无效请求:(我删除了 :: ErrorSignal.FromCurrentContext().Raise(ex);
,因为我不知道要添加哪个程序集......所以在您的测试中添加缺少的断言''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);
}
如果你真的需要,你可以模拟静态方法。这是我使用 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());
}