Untitled

mail@pastecode.io avatar
unknown
csharp
a year ago
6.0 kB
2
Indexable
Never
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using Polly;
using Xunit;

public class ResilienceTests
{
    private readonly Resilience _resilience;

    public ResilienceTests()
    {
        _resilience = new Resilience();
    }

    [Fact]
    public async Task RetryAsync_WithException_RetriesMethodToRetry()
    {
        // Arrange
        int retryTimes = 3;
        var cancellationToken = CancellationToken.None;
        var expectedException = new Exception("Simulated exception");
        var methodToRetryMock = new Mock<Func<Task<object>>>();
        var policyRulesMock = new Mock<Func<Exception, int, Action>>();
        policyRulesMock.Setup(pr => pr.Invoke(expectedException, It.IsAny<int>()))
            .Returns((Exception ex, int retryCount) => { });

        methodToRetryMock.SetupSequence(mtr => mtr.Invoke())
            .Throws(expectedException)
            .Returns(Task.FromResult(new object()));

        // Act
        var result = await _resilience.RetryAsync<Exception, object>(
            retryTimes,
            methodToRetryMock.Object,
            policyRulesMock.Object,
            cancellationToken);

        // Assert
        methodToRetryMock.Verify(mtr => mtr.Invoke(), Times.Exactly(retryTimes + 1));
        result.Should().NotBeNull();
    }

    [Fact]
    public async Task RetryAsync_WithSuccess_ReturnsMethodResult()
    {
        // Arrange
        int retryTimes = 3;
        var cancellationToken = CancellationToken.None;
        var expectedResult = new object();
        var methodToRetryMock = new Mock<Func<Task<object>>>();
        var policyRulesMock = new Mock<Func<Exception, int, Action>>();

        methodToRetryMock.Setup(mtr => mtr.Invoke())
            .Returns(Task.FromResult(expectedResult));

        // Act
        var result = await _resilience.RetryAsync<Exception, object>(
            retryTimes,
            methodToRetryMock.Object,
            policyRulesMock.Object,
            cancellationToken);

        // Assert
        methodToRetryMock.Verify(mtr => mtr.Invoke(), Times.Once);
        result.Should().Be(expectedResult);
    }

    [Fact]
    public async Task RetryAsync_WithExceptionAndTimeSpan_RetriesMethodToRetryWithWait()
    {
        // Arrange
        int retryTimes = 3;
        var cancellationToken = CancellationToken.None;
        var expectedException = new Exception("Simulated exception");
        var expectedWaitDuration = TimeSpan.FromSeconds(1);
        var methodToRetryMock = new Mock<Func<Task<object>>>();
        var policyRulesMock = new Mock<Func<Exception, TimeSpan, Action>>();
        var waitFunctionMock = new Mock<Func<int, TimeSpan>>();

        policyRulesMock.Setup(pr => pr.Invoke(expectedException, expectedWaitDuration))
            .Returns((Exception ex, TimeSpan waitDuration) => { });

        waitFunctionMock.Setup(wf => wf.Invoke(It.IsAny<int>()))
            .Returns(expectedWaitDuration);

        methodToRetryMock.SetupSequence(mtr => mtr.Invoke())
            .Throws(expectedException)
            .Returns(Task.FromResult(new object()));

        // Act
        var result = await _resilience.RetryAsync<Exception, object>(
            retryTimes,
            methodToRetryMock.Object,
            policyRulesMock.Object,
            waitFunctionMock.Object,
            cancellationToken);

        // Assert
        methodToRetryMock.Verify(mtr => mtr.Invoke(), Times.Exactly(retryTimes + 1));
        waitFunctionMock.Verify(wf => wf.Invoke(It.IsAny<int>()), Times.Exactly(retryTimes));
        result.Should().NotBeNull();
    }

    [Fact]
    public async Task HttpWaitAndRetryAsync_WithNonSuccessStatus_RetriesMethodToRetry()
    {
        // Arrange
        int retryTimes = 3;
        var cancellationToken = CancellationToken.None;
        var expectedResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError);
        var methodToRetryMock = new Mock<Func<Task<HttpResponseMessage>>>();
        var waitFunctionMock = new Mock<Func<int, TimeSpan>>();

        methodToRetryMock.SetupSequence(mtr => mtr.Invoke())
            .Returns(Task.FromResult(expectedResponse))
            .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)));

        waitFunctionMock.Setup(wf => wf.Invoke(It.IsAny<int>()))
            .Returns(TimeSpan.Zero);

        // Act
        var result = await _resilience.HttpWaitAndRetryAsync(
            retryTimes,
            methodToRetryMock.Object,
            waitFunctionMock.Object,
            cancellationToken);

        // Assert
        methodToRetryMock.Verify(mtr => mtr.Invoke(), Times.Exactly(2));
        waitFunctionMock.Verify(wf => wf.Invoke(It.IsAny<int>()), Times.Once);
        result.Should().Be(expectedResponse);
    }

    [Fact]
    public async Task HttpWaitAndRetryAsync_WithSuccessStatus_ReturnsMethodResult()
    {
        // Arrange
        int retryTimes = 3;
        var cancellationToken = CancellationToken.None;
        var expectedResult = new HttpResponseMessage(HttpStatusCode.OK);
        var methodToRetryMock = new Mock<Func<Task<HttpResponseMessage>>>();
        var waitFunctionMock = new Mock<Func<int, TimeSpan>>();

        methodToRetryMock.Setup(mtr => mtr.Invoke())
            .Returns(Task.FromResult(expectedResult));

        // Act
        var result = await _resilience.HttpWaitAndRetryAsync(
            retryTimes,
            methodToRetryMock.Object,
            waitFunctionMock.Object,
            cancellationToken);

        // Assert
        methodToRetryMock.Verify(mtr => mtr.Invoke(), Times.Once);
        waitFunctionMock.Verify(wf => wf.Invoke(It.IsAny<int>()), Times.Never);
        result.Should().Be(expectedResult);
    }
}