如何在单元测试 C# 中模拟 AuthenticationContext.AcquireTokenAsync
How to mock AuthenticationContext.AcquireTokenAsync in unit test C#
我有一个名为 GenerateJWTToken()
的方法来生成不记名令牌。它使用 AuthenticationContext
但是, AuthenticationContext
没有接口。我如何在单元测试中模拟它?
代码如下:
private async Task<string> GenerateJWTToken()
{
var instance = _configuration["AzureAd:Instance"];
var tenantId = _configuration["AzureAd:TenantId"];
var clientId = _configuration["AzureAd:ClientId"];
var clientSecret = _configuration.GetSection("appsecret").Value;
var resource = _configuration["AzureAd:Resource"];
var authority = string.Format("{0}{1}", instance, tenantId);
ClientCredential credential = new ClientCredential(clientId, clientSecret);
AuthenticationContext authContext = new AuthenticationContext(authority, false);
var result = await authContext.AcquireTokenAsync(resource, credential);
return result.AccessToken;
}
public async Task<HttpResponseMessage> GetResponseFromService(string userToken)
{
string endpoint = _configuration.GetSection("Service:Endpoint").Value;
var httpRequestMessage = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(endpoint)
};
var jwtToken = await GenerateJWTToken();
httpRequestMessage.Headers.Add("Authorization", "Bearer " + jwtToken);
httpRequestMessage.Headers.Add("token", userToken);
HttpResponseMessage httpResponseMessage = await _rpsRequest.ExecuteAsync(() => httpRequestMessage, maxRetry);
return httpResponseMessage
}
假设我们需要在 GetResponseFromService()
上编写单元测试,有人可以告诉我如何模拟 AuthenticationContext.AcquireTokenAsync
部分吗?谢谢!
您根本没有在 GenerateJWTToken 方法中使用依赖注入 - 您正在 GenerateJWTToken 内部创建对象 ClientCredential 和 AuthenticationContext - 这就是单元测试困难的原因。
并且也打破了 SOLID 的依赖倒置原则,即使你没有 "real interfaces".
将 ClientCredential 和 AuthenticationContext 的实例作为 GenerateJWTToken 和 GenerateJWTToken 参数传递 - 这样您就可以对其进行模拟和单元测试。在该代码中注入依赖项而不是创建新对象。
更新
现在我知道你可能是对的,除了一些 "fun" 和 Moq 或 wrapper class.
之外别无选择
主要问题 - 为什么在实际支持 MSAL 库的情况下使用旧的、有点过时的 ADAL? MSAL 支持接口等https://docs.microsoft.com/pl-pl/azure/active-directory/develop/msal-net-migration#differences-between-adal-and-msal-apps
来自 github:
This library, ADAL for .NET, will no longer receive new feature
improvements. Instead, use the new library MSAL for .NET.
https://github.com/AzureAD/microsoft-authentication-library-for-dotnet
经过一些research,我意识到 ADAL 不可单元测试,我们不测试 ADAL 本身。因此,我所做的是将 GenerateJWTToken
提取到具有其界面的新 class 中。并在具有 GetResponseFromService()
方法的 class 上使用依赖注入。
我有一个名为 GenerateJWTToken()
的方法来生成不记名令牌。它使用 AuthenticationContext
但是, AuthenticationContext
没有接口。我如何在单元测试中模拟它?
代码如下:
private async Task<string> GenerateJWTToken()
{
var instance = _configuration["AzureAd:Instance"];
var tenantId = _configuration["AzureAd:TenantId"];
var clientId = _configuration["AzureAd:ClientId"];
var clientSecret = _configuration.GetSection("appsecret").Value;
var resource = _configuration["AzureAd:Resource"];
var authority = string.Format("{0}{1}", instance, tenantId);
ClientCredential credential = new ClientCredential(clientId, clientSecret);
AuthenticationContext authContext = new AuthenticationContext(authority, false);
var result = await authContext.AcquireTokenAsync(resource, credential);
return result.AccessToken;
}
public async Task<HttpResponseMessage> GetResponseFromService(string userToken)
{
string endpoint = _configuration.GetSection("Service:Endpoint").Value;
var httpRequestMessage = new HttpRequestMessage()
{
Method = HttpMethod.Get,
RequestUri = new Uri(endpoint)
};
var jwtToken = await GenerateJWTToken();
httpRequestMessage.Headers.Add("Authorization", "Bearer " + jwtToken);
httpRequestMessage.Headers.Add("token", userToken);
HttpResponseMessage httpResponseMessage = await _rpsRequest.ExecuteAsync(() => httpRequestMessage, maxRetry);
return httpResponseMessage
}
假设我们需要在 GetResponseFromService()
上编写单元测试,有人可以告诉我如何模拟 AuthenticationContext.AcquireTokenAsync
部分吗?谢谢!
您根本没有在 GenerateJWTToken 方法中使用依赖注入 - 您正在 GenerateJWTToken 内部创建对象 ClientCredential 和 AuthenticationContext - 这就是单元测试困难的原因。 并且也打破了 SOLID 的依赖倒置原则,即使你没有 "real interfaces".
将 ClientCredential 和 AuthenticationContext 的实例作为 GenerateJWTToken 和 GenerateJWTToken 参数传递 - 这样您就可以对其进行模拟和单元测试。在该代码中注入依赖项而不是创建新对象。
更新
现在我知道你可能是对的,除了一些 "fun" 和 Moq 或 wrapper class.
之外别无选择
主要问题 - 为什么在实际支持 MSAL 库的情况下使用旧的、有点过时的 ADAL? MSAL 支持接口等https://docs.microsoft.com/pl-pl/azure/active-directory/develop/msal-net-migration#differences-between-adal-and-msal-apps
来自 github:
This library, ADAL for .NET, will no longer receive new feature improvements. Instead, use the new library MSAL for .NET.
https://github.com/AzureAD/microsoft-authentication-library-for-dotnet
经过一些research,我意识到 ADAL 不可单元测试,我们不测试 ADAL 本身。因此,我所做的是将 GenerateJWTToken
提取到具有其界面的新 class 中。并在具有 GetResponseFromService()
方法的 class 上使用依赖注入。