我正在尝试使用 Web API2、JWT、Microsoft.IdentityModel.JsonWebTokens 5.2.422 和本文中概述的 token 验证逻辑:http://www.decatechlabs.com/secure-webapi-using-jwt
当我重复文章中的步骤(包括通过 ReSTLet 测试 API)时,一切对我的项目都很有用。但是,我正在尝试为此项目使用测试驱动开发 (TDD),并且我希望测试所有内容在我的测试中是否正常工作,包括 token 验证处理程序。如果我在单元测试中直接调用它们,我可以测试我的 Controller ,但这绕过了实际的 token 验证处理程序。因此,我尝试使用自托管 HTTP 来正确执行完整的 API,包括所有 token 验证处理程序逻辑。这是我获取 token 然后将 token 传递给需要授权的第二种方法的完整单元测试:
[TestMethod]
public void GetAuthorizedStatus_SelfHostedHTTP()
{
HttpServer server = TestAPIHelper.GenerateTestServer();
using (HttpMessageInvoker client = new HttpMessageInvoker(server))
{
string token = string.Empty;
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, loginURL))
{
var stringContent = new StringContent(JsonConvert.SerializeObject(TestAPIHelper.loginObject), Encoding.UTF8, "application/json");
request.Content = stringContent;
using (HttpResponseMessage response = client.SendAsync(request, System.Threading.CancellationToken.None).Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Error getting token from login portion");
token = response.Content.ReadAsAsync<string>().Result;
Assert.IsTrue(token.Length > 50);
}
}
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, authorizedStatusURL))
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using (HttpResponseMessage response = client.SendAsync(request, System.Threading.CancellationToken.None).Result)
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Error getting status from Authenticated portion.");
}
}
};
}
问题是 TokenValidationHandler 抛出“未将对象引用设置为对象的实例”。处理程序的以下两行中的第二行异常,仅当我的单元测试调用并附加 token 时。如果我使用 ReSTLet/Postman/whatever 触发处理程序,则不会引发异常并且一切正常。
Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);
当第一行几乎相同的行工作时,我不明白是什么导致仅第二行出错 - 两行调用相同的方法。而且我不明白为什么它适用于第三方软件但不适用于我的测试代码 - 我担心的是,如果我不为单元测试弄清楚这一点,那么我将无法使代码适用于调用此 api 的真实应用程序。我认为这是我的测试代码中的一些微不足道的设置,我需要在提交之前添加到我的请求中。但也许我需要构建一种完全不同的方法来在我的单元测试中调用 API。
最佳答案
我不会这样做。
在这种情况下,我所做的是编写涵盖 token 逻辑的集成测试。
这意味着调用 token 端点,检索 token ,然后调用其他内容并查看会发生什么。
然后,您可以添加其他测试,例如当 token 丢失、无效、过期或包含错误声明时会发生什么。
关于c# - 使用 Web API 对 JWT token 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51353294/