我正在使用默认的 azure 凭据方法获取访问令牌,同时使用函数应用程序的托管标识获取访问令牌。我能够获取令牌。但现在我不确定我将如何对该方法进行单元测试。这是目前的状态
private async Task RefreshTokenCache()
{
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { _config[AppConstants.ADAPIAppId] + "/.default" }) { });
accessTokenCache.Set(AppConstants.AccessToken, accessToken.Token, DateTimeOffset.Now.AddMinutes(55));
}
是否有类似 httpclientfactory 之类的东西,我可以在其中注入或传递一些连接字符串,以便我告诉 DefaultAzureCredential 不要调用 Azure?
更新
我正在添加更多上下文。我正在使用它从 azure 获取我的函数应用程序中的访问令牌,以向 APIM 进行身份验证。所以我使用了 HttpMessageHandler,因为我正在检查令牌是否不存在,请调用 Azure 并获取令牌。
在函数应用中启动。
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddHttpClient(AppConstants.ReplyService)
//Adding token handler middleware to add authentication related details.
.AddHttpMessageHandler<AccessTokenHandler>();
}
处理程序文件:
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
// Use the token to make the call.
// other details
request.Headers.Authorization = new AuthenticationHeaderValue(AppConstants.AuthHeader, await GetToken());
return await base.SendAsync(request, cancellationToken);
}
private async Task<string> GetToken(bool needsRefresh = false)
{
if (accessTokenCache.GetCount() == 0 || needsRefresh)
{
var tokenCredential = new DefaultAzureCredential();
var accessToken = await tokenCredential.GetTokenAsync(
new TokenRequestContext(scopes: new string[] { _config["AppId"] + "/.default" }) { });
accessTokenCache.Set("accessToken", accessToken.Token, DateTimeOffset.Now.AddMinutes(55));
}
return accessTokenCache.Get("accessToken")?.ToString() ?? throw new Exception("Unable to Fetch Access Token from Cache");
}
答案 0 :(得分:1)
您不应该像这样使用 DefaultAzureCredential
。它需要作为 DI 层的一部分注入到服务中,例如这里我正在设置一个新的 BlobServiceClient
:
private static void addAzureClients(IFunctionsHostBuilder builder)
{
builder.Services.AddAzureClients(builder =>
{
try
{
builder.AddBlobServiceClient(Environment.GetEnvironmentVariable("AzureWebJobsStorage"));
builder.UseCredential(new DefaultAzureCredential());
}
catch(Exception ex)
{
throw new Exception($"Error loading AddBlobServiceClient: {Environment.GetEnvironmentVariable("AzureWebJobsStorage")}", ex);
}
});
}
然后我使用依赖注入来消耗客户端:
public MyClass(BlobServiceClient blobServiceClient)
{
this.blobServiceClient = blobServiceClient;
}
而且我根本不需要接触 DefaultAzureCredential
类。然后在单元测试时我模拟 BlobServiceClient
这是一个抽象类。
如果您确实确定要实际使用 DefaultAzureCredential
,那么您的答案仍然是依赖注入。我建议你这样设置:
在您的启动中:
builder.Services.AddSingleton<TokenCredential>(() => new DefaultAzureCredential());
然后(很像上面)将其注入您的类:
public MyClass(TokenCredential tokenCredential)
{
this.tokenCredential= tokenCredential;
}
然后在测试中模拟 TokenCredential
。您不能模拟您new
的课程。所以你现在需要这样做