Testing Polly retry policy with moq
Asked Answered
W

1

10

I'm trying to write a unit test for polly, but it looks like the return is cached.

Method 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;
    }
}

Test:

[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");
    }

}

Not sure why, but it looks like the responses queue is only being Dequeue once, this leads me to believe the response is being cache. Does anyone know who is caching the response, and how do I disable it?

Thanks a bunch in advance!

Wheeze answered 17/11, 2017 at 0:52 Comment(3)
Please try to provide real minimal reproducible example as it is not clear how those two fragments interact. Side note: Using .Result make method non async and likely to deadlock... But it is unlikely to be problem in unit test.Meldon
Here are some you could take a look at: github.com/App-vNext/Polly/blob/master/src/Polly.SharedSpecs/…Eugeneeugenia
current url for RetrySpec.cs shared by @ScottHannenAccessory
W
9

I figured it out. It has nothing to do with caching. During the mock setup, it stores the Dequeue value as a return instead of invoking it every time. Changing it to () => responses.Dequeue() works now.

Thank you guys!

Wheeze answered 17/11, 2017 at 17:39 Comment(1)
Thank you for asking and answering the question. It has helped me a lot todayNiall

© 2022 - 2024 — McMap. All rights reserved.