Full source code here.
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.
[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.
[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.
[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.