File: Polly\HttpCircuitBreakerStrategyOptionsTests.cs
Web Access
Project: src\test\Libraries\Microsoft.Extensions.Http.Resilience.Tests\Microsoft.Extensions.Http.Resilience.Tests.csproj (Microsoft.Extensions.Http.Resilience.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using FluentAssertions;
using Polly;
using Polly.CircuitBreaker;
using Polly.Timeout;
using Xunit;
 
namespace Microsoft.Extensions.Http.Resilience.Test.Polly;
 
public class HttpCircuitBreakerStrategyOptionsTests
{
#pragma warning disable S2330
    public static readonly IEnumerable<object[]> HandledExceptionsClassified = new[]
    {
        new object[] { new InvalidCastException(), false },
        new object[] { new HttpRequestException(), true },
        new object[] { new TaskCanceledException(), false },
        new object[] { new TimeoutRejectedException(), true },
    };
 
    private readonly HttpCircuitBreakerStrategyOptions _testObject;
    private readonly ResilienceContext _context;
 
    public HttpCircuitBreakerStrategyOptionsTests()
    {
        _testObject = new HttpCircuitBreakerStrategyOptions();
        _context = ResilienceContextPool.Shared.Get();
    }
 
    [Fact]
    public void Ctor_Defaults()
    {
        _testObject.BreakDuration.Should().Be(TimeSpan.FromSeconds(5));
        _testObject.FailureRatio.Should().Be(0.1);
        _testObject.SamplingDuration.Should().Be(TimeSpan.FromSeconds(30));
        _testObject.MinimumThroughput.Should().Be(100);
        _testObject.ShouldHandle.Should().NotBeNull();
        _testObject.OnClosed.Should().BeNull();
        _testObject.OnOpened.Should().BeNull();
        _testObject.OnHalfOpened.Should().BeNull();
    }
 
    [Theory]
    [InlineData(HttpStatusCode.OK, false)]
    [InlineData(HttpStatusCode.BadRequest, false)]
    [InlineData(HttpStatusCode.RequestEntityTooLarge, false)]
    [InlineData(HttpStatusCode.InternalServerError, true)]
    [InlineData(HttpStatusCode.HttpVersionNotSupported, true)]
    [InlineData(HttpStatusCode.RequestTimeout, true)]
    public async Task ShouldHandleResultAsError_DefaultValue_ShouldClassify(HttpStatusCode statusCode, bool expectedCondition)
    {
        using var response = new HttpResponseMessage { StatusCode = statusCode };
        var isTransientFailure = await _testObject.ShouldHandle(CreateArgs(response));
        Assert.Equal(expectedCondition, isTransientFailure);
    }
 
    [Theory]
    [MemberData(nameof(HandledExceptionsClassified))]
    public async Task ShouldHandleException_DefaultValue_ShouldClassify(Exception exception, bool expectedToHandle)
    {
        var shouldHandle = await _testObject.ShouldHandle(CreateArgs(exception));
        Assert.Equal(expectedToHandle, shouldHandle);
    }
 
    private CircuitBreakerPredicateArguments<HttpResponseMessage> CreateArgs(Exception error)
        => new(_context, Outcome.FromException<HttpResponseMessage>(error));
 
    private CircuitBreakerPredicateArguments<HttpResponseMessage> CreateArgs(HttpResponseMessage response)
        => new(_context, Outcome.FromResult(response));
 
}