Testing Your Code When Using Polly

Full source code here.

Want to learn more about Polly? Check out my Pluralsight course on it.

When developing an application with Polly you will also probably want to write some unit tests.

Here are the scenarios I test for -

  1. How my code behaves when the policy throws an exception, such as TimeoutRejectionException, BulkheadRejectedException or BrokenCircuitException.
  2. How my code behaves when a policy becomes active and changes the outcome of a call, such as when an unreliable request works because Polly performs a retry.
  3. What my code should do if there was no policy in place.

I have a few classes to demonstrate these scenarios, BusinessLogic.cs and OtherBusinessLogic.cs are the classes under test. ErrorProneCode.cs is the unreliable class that I will mock and pass mocked policies into.

For the first case I use Moq to mock the error prone code so it returns an incorrect value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[Fact]
public void Should_Return_999_When_TimeoutRejectedException_Thrown()
{
    //Arrange 
    Mock<IErrorProneCode> mockedErrorProneCode = new Mock<IErrorProneCode>();
    mockedErrorProneCode.Setup(e => e.GetSomeNumber()).Returns(0);

    Mock<ISyncPolicy> mockedPolicy = new Mock<ISyncPolicy>();
    mockedPolicy.Setup(p => p.Execute(It.IsAny<Func<int>>())).Throws(new TimeoutRejectedException("Mocked Timeout Exception"));

    IBusinessLogic businessLogic = new BusinessLogic(mockedPolicy.Object, mockedErrorProneCode.Object);

    //Act
    // if there is a TimeoutRejectedException in this CallSomeSlowBadCode it will return 999
    int num = businessLogic.CallSomeSlowBadCode();

    //Assert
    Assert.Equal(999, num);
}

In the next case I verify that the application has correctly used the retry policy method. I use a seeded random number generator that produces an known sequence to return values from the ErrorProneCode class.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
[Fact]
public void Should_Return_Odd_When_Retry()
{
    //Arrange 
    Mock<IErrorProneCode> mockedErrorProneCode = new Mock<IErrorProneCode>();

    Random rnd = new Random(1); // rnd.Next(10) retruns 2, 1, 4 

    mockedErrorProneCode.Setup(e => e.GetSomeNumber()).Returns(() => rnd.Next(10));

    ISyncPolicy<int> policy = Policy.HandleResult<int>(i => i %2 !=1) // retry if the number is not odd.
        .Retry(1);
    OtherBusinessLogic otherBusinessLogic = new OtherBusinessLogic(policy, mockedErrorProneCode.Object);

    //Act
    int num = otherBusinessLogic.CallSomeCodeThatNeedsToBeRetried();

    //Assert
    Assert.Equal(1, num % 2);
}

Finally, I want to verify that my code will work if no Polly policy is in use. To do this, I pass in a NoOp policy.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
[Fact]
public void Should_Return_Even_With_NoOp()
{
    //Arrange 
    Mock<IErrorProneCode> mockedErrorProneCode = new Mock<IErrorProneCode>();

    Random rnd = new Random(1); // rnd.Next(10) retruns 2, 1, 4 

    mockedErrorProneCode.Setup(e => e.GetSomeNumber()).Returns(() => rnd.Next(10));

    ISyncPolicy<int> policy = Policy.NoOp<int>();
    OtherBusinessLogic otherBusinessLogic = new OtherBusinessLogic(policy, mockedErrorProneCode.Object);

    //Act
    int num = otherBusinessLogic.CallSomeCodeThatNeedsToBeRetried();

    //Assert
    Assert.Equal(0, num % 2); //even number
}

Full source code here.

comments powered by Disqus

Related