使用moq测试Polly重试策略

时间:2017-11-17 00:52:15

标签: c# unit-testing moq polly

我正在尝试为polly编写单元测试,但它看起来像是缓存了返回。

方法PostAsyncWithRetry:

using Polly;
using System;
using System.Diagnostics;
using System.Net.Cache;
using System.Net.Http;
public class RetryClient
{
    private HttpClient httpClient = new HttpClient(new WebRequestHandler()
    { CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore) });

    public HttpResponseMessage PostAsyncWithRetry(
        String url,
        String path,
        StringContent httpContent)
    {
        httpClient.BaseAddress = new Uri(url);

        var retryPolicy =
            Policy.Handle<HttpRequestException>()
            .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
            .RetryAsync(3, (exception, retryCount, context) =>
            {
                Debug.WriteLine("RetryCount: {0}", retryCount);
            });

        var response = retryPolicy.ExecuteAsync(async () =>
        {
            return await httpClient.PostAsync(path, httpContent);
        }
        );

        return response.Result;
    }
}

测试:

[TestFixture]
class Test
{
    private HttpClient mockHTTPClient;
    private Mock<WebRequestHandler> mockHttpMessageHandler;
    private RetryClient testInstance;

    private const String URL = "https://aaa.com";
    private const String PATH = "/path";
    private const String EXPECTED_STRING_CONTENT = "Some return text";

    [SetUp]
    public void SetUp()
    {
        testInstance = new RetryClient();
        mockHttpMessageHandler = new Mock<WebRequestHandler>();
        mockHttpMessageHandler.Object.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);

        mockHTTPClient = new HttpClient(mockHttpMessageHandler.Object);

        var type = typeof(RetryClient);
        var fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
        fields[0].SetValue(testInstance, mockHTTPClient);
    }

    [Test]
    public void TestMEEEE()
    {
        var responses = new Queue<Task<HttpResponseMessage>>();
        responses.Enqueue(Task.FromResult(new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.NotFound,
            Content = new StringContent(EXPECTED_STRING_CONTENT)
        }));
        responses.Enqueue(Task.FromResult(new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(EXPECTED_STRING_CONTENT)
        }));

        var postContent = new StringContent(EXPECTED_STRING_CONTENT);
        mockHttpMessageHandler.Protected()
           .Setup<Task>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
           .Returns(responses.Dequeue());

        var response = testInstance.PostAsyncWithRetry(
            URL, PATH, postContent);

        mockHttpMessageHandler.Verify();
        Assert.AreEqual(responses.Count, 0, "didn't dequeue");
        Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Incorrect status code");
    }

}

不确定原因,但看起来响应队列只是一次Dequeue,这让我相信响应正在缓存。有谁知道谁在缓存响应,我该如何禁用它?

提前感谢一大堆!

1 个答案:

答案 0 :(得分:1)

我明白了。它与缓存无关。在模拟设置期间,它将Dequeue值存储为返回值,而不是每次都调用它。 将其更改为()=&gt; respond.Dequeue()现在有效。

谢谢你们!