I have .net core weabpi (see code below). I am using polly retry policy (see policy below). I would like to unit test endpoint (getProducts) and test polly retry
I have found these examples but it is not clear how to unit test endpoint and retry policy?
services
.AddHttpClient<IProductService, ProductService>()
.AddPolicyHandler(GetRetryPolicy(3, 2));
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy(int retryCount, int breakDuration)
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(breakDuration,
retryAttempt)));
}
.Net core api:
public interface IProductService
{
Task<IEnumerable<ProductResponse>> GetProducts(string productType);
}
public class ProductService: IProductService
{
private readonly HttpClient _httpClient;
public ProductService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<IEnumerable<ProductResponse>> GetProducts(string productType)
{
var response = await _httpClient.GetAsync("uri");
...
}
}
Update (02/21/24)
In case of V8 you can make assertions against the strategies' options. In this Polly version the strategies behavior can be configures via XYZStrategyOptions
. And gladly these objects are retrievable after you have created your pipeline.
Here you can find the related documentation page
// Retrieve the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();
// Check the pipeline's composition with the descriptor.
Assert.Equal(2, descriptor.Strategies.Count);
// Verify the retry settings.
var retryOptions = Assert.IsType<RetryStrategyOptions>(descriptor.Strategies[0].Options);
Assert.Equal(4, retryOptions.MaxRetryAttempts);
// Confirm the timeout settings.
var timeoutOptions = Assert.IsType<TimeoutStrategyOptions>(descriptor.Strategies[1].Options);
Assert.Equal(TimeSpan.FromSeconds(1), timeoutOptions.Timeout);
The sad truth is you can't really unit test your retry+endpoint logic and here are my reasoning:
HttpClient
via the DI (AddPolicyHandler
). When you are unit testing then you are not relying on the DI rather on individual components.Back to your test case. The correct way to articulate your test scenario with the given-when-then structure should be written like this
This is not a unit test. It is more like a component/integration test. Why? Because even though you could create an HttpClient mock but in that case there will be no retry policy there.
There is a workaround: you could manually decorate the underlying handler with the policy via the PolicyHttpMessageHandler
. But that's a bad idea in a unit test, because you basically re-implemented the DI part inside your test. And with that you would test your test arrangement code, not your production code.