如何在单元测试 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 上使用依赖注入。