Как выполнить модульное тестирование метода DefaultAzureCredential
Я получаю токен доступа с помощью метода учетных данных 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");
}
1 ответ
Вы не должны так использовать. Его необходимо ввести в эксплуатацию как часть уровня DI, например, здесь я настраиваю новый:
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;
}
и мне вообще никогда не нужно прикасаться к классу. Затем при модульном тестировании я издеваюсь над
BlobServiceClient
который является абстрактным классом.
Если вы действительно уверены, что действительно хотите использовать
DefaultAzureCredential
то ваш ответ по-прежнему - инъекция зависимостей. Я предлагаю вам настроить это так:
В вашем стартапе:
builder.Services.AddSingleton<TokenCredential>(() => new DefaultAzureCredential());
Затем (как и выше) введите это в свой класс:
public MyClass(TokenCredential tokenCredential)
{
this.tokenCredential= tokenCredential;
}
Тогда в своем тесте вы издеваетесь
TokenCredential
. Вы не можете издеваться над классом, который вы
new
. Итак, вам нужно сделать это сейчас