> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/App-vNext/Polly/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing

> Test resilience pipelines using the Polly.Testing package

This document explains how to test Polly's resilience pipelines. You should not test how the resilience pipelines operate internally, but rather test your own settings or custom delegates.

To make the testing process simpler, Polly offers the [`Polly.Testing`](https://www.nuget.org/packages/Polly.Testing/) package. This package has a range of APIs designed to help you test the setup and combination of resilience pipelines in your user code.

## Installation

Begin by adding the [`Polly.Testing`](https://www.nuget.org/packages/Polly.Testing) package to your test project:

```bash theme={null}
dotnet add package Polly.Testing
```

## Basic Usage

Use the `GetPipelineDescriptor` extension method to get the `ResiliencePipelineDescriptor` which provides details on the pipeline's composition:

```csharp theme={null}
// Build your resilience pipeline.
ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
    .AddRetry(new RetryStrategyOptions
    {
        MaxRetryAttempts = 4
    })
    .AddTimeout(TimeSpan.FromSeconds(1))
    .Build();

// 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);
```

## Testing Generic Pipelines

The `GetPipelineDescriptor` extension method is also available for the generic `ResiliencePipeline<T>`:

```csharp theme={null}
// Construct your resilience pipeline.
ResiliencePipeline<string> pipeline = new ResiliencePipelineBuilder<string>()
    .AddRetry(new RetryStrategyOptions<string>
    {
        MaxRetryAttempts = 4
    })
    .AddTimeout(TimeSpan.FromSeconds(1))
    .Build();

// Obtain the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();

// Check the pipeline's composition with the descriptor.
// ...
```

## Mocking ResiliencePipelineProvider

Consider the following code that might resemble a part of your project:

```csharp theme={null}
// Represents an arbitrary API that needs resilience support
public class MyApi
{
    private readonly ResiliencePipeline _pipeline;

    // The value of pipelineProvider is injected via dependency injection
    public MyApi(ResiliencePipelineProvider<string> pipelineProvider)
    {
        _pipeline = pipelineProvider.GetPipeline("my-pipeline");
    }

    public async Task ExecuteAsync(CancellationToken cancellationToken)
    {
        await _pipeline.ExecuteAsync(
            static async token =>
            {
                // Add your code here
            },
            cancellationToken);
    }
}

// Extensions to incorporate MyApi into dependency injection
public static class MyApiExtensions
{
    public static IServiceCollection AddMyApi(this IServiceCollection services)
    {
        return services
            .AddResiliencePipeline("my-pipeline", builder =>
            {
                builder.AddRetry(new RetryStrategyOptions
                {
                    MaxRetryAttempts = 4
                });
            })
            .AddSingleton<MyApi>();
    }
}
```

In the example above:

* The `MyApi` class is introduced, representing part of your application that requires resilience support.
* The `AddMyApi` extension method is also defined, which integrates `MyApi` into dependency injection (DI) and sets up the resilience pipeline it uses.

### Mocking Example

For unit tests, if you want to assess the behavior of `ExecuteAsync`, it might not be practical to rely on the entire pipeline, especially since it could slow down tests during failure scenario evaluations. Instead, it's recommended to mock the `ResiliencePipelineProvider<string>` and return an empty pipeline:

```csharp theme={null}
ResiliencePipelineProvider<string> pipelineProvider = Substitute.For<ResiliencePipelineProvider<string>>();

// Mock the pipeline provider to return an empty pipeline for testing
pipelineProvider
    .GetPipeline("my-pipeline")
    .Returns(ResiliencePipeline.Empty);

// Use the mocked pipeline provider in your code
var api = new MyApi(pipelineProvider);

// You can now test the api
```

<Note>
  This example leverages the [`NSubstitute`](https://github.com/nsubstitute/NSubstitute) library to mock the pipeline provider.
</Note>

## Best Practices

<CardGroup cols={2}>
  <Card title="Test Configuration" icon="gear">
    Focus on testing your resilience pipeline configuration and custom delegates, not the internal behavior of Polly strategies.
  </Card>

  <Card title="Use Descriptors" icon="file-contract">
    Use `GetPipelineDescriptor()` to verify that your pipeline is composed correctly with the right strategies and options.
  </Card>

  <Card title="Mock in Unit Tests" icon="mask">
    Mock `ResiliencePipelineProvider` in unit tests to avoid slow tests and focus on testing your application logic.
  </Card>

  <Card title="Integration Tests" icon="vial">
    Use real resilience pipelines in integration tests to verify end-to-end behavior with actual resilience strategies.
  </Card>
</CardGroup>
