C# Mocked (Moq) Method not being called

可紊 提交于 2021-01-05 07:25:44

问题


I am trying to test an API client, but for some reason, I do not see one of the my internal methods being called. Specially, it seems that the AdminClient.MakeHttpCall is never called (based on my breakpoint set there there). Unsure what I am missing here, and have used Moq before.

**** EDIT **** To clarify, in GetUserAsync method, line var response = await MakeHttpCall(HttpMethod.Get, $"/api/customadmin/user/id/{id}");, the variable response is null, and it doesn't seem like the debugger ever enters MakeHttpCall method.

Test method:

[Fact]
[Trait("Category", "AdminClient")]
public async Task ExpiredToken_OnlyTryToRetrieveAccessTokenOnce()
{
    int numNonRetryCalls = 0;
    int numRetryCalls = 0;
    var config = GetConfig();

    var unauthorizedResponse = new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
    var mock = new Mock<AdminClient>(config);

    // Set up initial call that returns unauthorized
    mock.Setup(x => x.MakeHttpCallInternal(AdminClient.HttpMethod.Get, It.IsAny<string>(), null, false))
        .ReturnsAsync(unauthorizedResponse)
        .Callback(() => numNonRetryCalls++);

    // Set up retry call that returns unauthorized
    mock.Setup(x => x.MakeHttpCallInternal(AdminClient.HttpMethod.Get, It.IsAny<string>(), null, true))
        .ReturnsAsync(unauthorizedResponse)
        .Callback(() => numRetryCalls++);

    var result = await mock.Object.GetUserAsync(1);

    Assert.Equal(1, numNonRetryCalls);
    Assert.Equal(1, numRetryCalls);
}

AdminClient:

public class AdminClient : IAdminClient
{
    public enum HttpMethod
    {
        Get,
        Post,
        Put,
        Delete
    }

    private readonly AppMgmtConfig _config;
    private HttpClient _httpClient;

    public AdminClient(AppMgmtConfig config)
    {
        _config = config;
        InitializeHttpClient().Wait();
    }

    private async Task InitializeHttpClient()
    {
        if (_httpClient == null)
        {
            _httpClient = new HttpClient();
            Uri baseUri;
            Uri.TryCreate(_config.ManagementAPIUrl, UriKind.RelativeOrAbsolute, out baseUri);
            _httpClient.BaseAddress = baseUri ?? throw new ArgumentException("Invalid ManagementAPI URL", "ManagementAPIUrl");
            var accessToken = (await _config.GetAccessToken()).AccessToken;
            var authHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken);
            _httpClient.DefaultRequestHeaders.Authorization = authHeaderValue;
        }
    }

    /// <summary>
    /// Get user using the integer ID.
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<CrudOperationResult<DbUser>> GetUserAsync(int id)
    {
        var response = await MakeHttpCall(HttpMethod.Get, $"/api/customadmin/user/id/{id}");
        string contentString = await GetStringContentFromResponseMessage(response);

        var result = JsonConvert.DeserializeObject<CrudOperationResult<DbUser>>(contentString);
        return result;
    }

    internal virtual async Task<HttpResponseMessage> MakeHttpCall(HttpMethod httpMethod, string url, HttpContent content = null)
    {
        try
        {
            var response = await MakeHttpCallInternal(httpMethod, url, content, false);
            response.EnsureSuccessStatusCode();
            return response;
        }
        catch
        {
            await GetNewAccessToken();
            var response = await MakeHttpCallInternal(httpMethod, url, content, true);
            response.EnsureSuccessStatusCode();
            return response;
        }
    }

    internal virtual async Task<HttpResponseMessage> MakeHttpCallInternal(HttpMethod httpMethod, string url, HttpContent content = null, bool isRetryRequest = false)
    {
        HttpResponseMessage responseMessage = null;

        if (httpMethod == HttpMethod.Get)
        {
            responseMessage = await _httpClient.GetAsync(url);
        }
        else if (httpMethod == HttpMethod.Post)
        {
            responseMessage = await _httpClient.PostAsync(url, content);
        }
        else if (httpMethod == HttpMethod.Delete)
        {
            responseMessage = await _httpClient.DeleteAsync(url);
        }

        return responseMessage;
    }

    internal async Task GetNewAccessToken()
    {
        var accessToken = (await _config.GetAccessToken()).AccessToken;
        if (!String.IsNullOrEmpty(accessToken))
        {
            var authHeaderValue = new AuthenticationHeaderValue("Bearer", accessToken);
            _httpClient.DefaultRequestHeaders.Authorization = authHeaderValue;
        }
    }

    private async Task<string> GetStringContentFromResponseMessage(HttpResponseMessage message)
    {
        return await message.Content.ReadAsStringAsync();
    }
}

来源:https://stackoverflow.com/questions/47043408/c-sharp-mocked-moq-method-not-being-called

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!