使用最小起订量测试 Polly 重试策略

Posted

技术标签:

【中文标题】使用最小起订量测试 Polly 重试策略【英文标题】:Testing Polly retry policy with moq 【发布时间】:2017-11-17 00:52:14 【问题描述】:

我正在尝试为 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");
    


不知道为什么,但看起来响应队列只是出队一次,这让我相信响应正在缓存。有谁知道谁在缓存响应,以及如何禁用它?

提前致谢!

【问题讨论】:

请尝试提供真实的minimal reproducible example,因为不清楚这两个片段如何交互。旁注:使用.Result 使方法非异步并可能死锁......但在单元测试中不太可能出现问题。 这里有一些你可以看看:github.com/App-vNext/Polly/blob/master/src/Polly.SharedSpecs/… @ScottHannen 共享的RetrySpec.cs 的当前网址 【参考方案1】:

我想通了。它与缓存无关。在模拟设置期间,它将 Dequeue 值存储为返回值,而不是每次都调用它。 将其更改为 () =>responses.Dequeue() 现在可以使用。

谢谢你们!

【讨论】:

感谢您提出并回答问题。今天对我帮助很大

以上是关于使用最小起订量测试 Polly 重试策略的主要内容,如果未能解决你的问题,请参考以下文章

通过 Polly 重试策略确定最终重试的完成

Polly 重试策略

使用最小起订量模拟静态属性

Polly的多种弹性策略介绍和简单使用

如何最小起订量实体框架 SqlQuery 调用

如何最小起订量委托回调和 lambda 方法