public async Task ShouldNotThrowIfNotCanceled(
                RequestMessage message,
                HttpStatusCode statusCode,
                [Target] SqsRequestMessageRelay relay,
                CancellationToken cancellationToken
                )
            {
                Func <Task> func = () => relay.Complete(message, statusCode, null, cancellationToken);

                await func.Should().NotThrowAsync <OperationCanceledException>();
            }
            public async Task ShouldThrowIfCanceled(
                RequestMessage message,
                HttpStatusCode statusCode,
                [Target] SqsRequestMessageRelay relay
                )
            {
                var         cancellationToken = new CancellationToken(true);
                Func <Task> func = () => relay.Complete(message, statusCode, null, cancellationToken);

                await func.Should().ThrowAsync <OperationCanceledException>();
            }
            public async Task ShouldSetMessageStateToSucceeded(
                RequestMessage message,
                HttpStatusCode statusCode,
                [Frozen] RequestOptions options,
                [Frozen, Substitute] IAmazonSQS sqs,
                [Target] SqsRequestMessageRelay relay,
                CancellationToken cancellationToken
                )
            {
                await relay.Complete(message, statusCode, null, cancellationToken);

                message.State.Should().Be(RequestMessageState.Succeeded);
            }
            public async Task ShouldPropagateDeleteMessageBatchExceptions(
                RequestMessage message,
                HttpStatusCode statusCode,
                Exception exception,
                [Frozen] RequestOptions options,
                [Frozen, Substitute] IAmazonSQS sqs,
                [Target] SqsRequestMessageRelay relay,
                CancellationToken cancellationToken
                )
            {
                sqs.DeleteMessageBatchAsync(Any <DeleteMessageBatchRequest>(), Any <CancellationToken>()).Throws(exception);

                Func <Task> func = () => relay.Complete(message, statusCode, null, cancellationToken);

                (await func.Should().ThrowAsync <Exception>())
                .And.Should().Be(exception);
            }
 public async Task ShouldThrowIfMessageFailedToDelete(
     string response,
     HttpStatusCode statusCode,
     RequestMessage message,
     Exception exception,
     [Frozen] ISerializer serializer,
     [Frozen] RequestOptions options,
     [Frozen, Substitute] IAmazonSQS sqs,
     [Target] SqsRequestMessageRelay relay,
     CancellationToken cancellationToken
     )
 {
     sqs.DeleteMessageBatchAsync(Any <DeleteMessageBatchRequest>(), Any <CancellationToken>()).Returns(new DeleteMessageBatchResponse
     {
         Failed = new List <BatchResultErrorEntry>
         {
             new() { Id = message.RequestDetails.Id.ToString() },
         },
     });
            public async Task ShouldDeleteMessageFromTheQueue(
                RequestMessage message,
                HttpStatusCode statusCode,
                [Frozen] RequestOptions options,
                [Frozen, Substitute] IAmazonSQS sqs,
                [Target] SqsRequestMessageRelay relay,
                CancellationToken cancellationToken
                )
            {
                await relay.Complete(message, statusCode, null, cancellationToken);

                await sqs.Received().DeleteMessageBatchAsync(
                    Is <DeleteMessageBatchRequest>(req =>
                                                   req.Entries.Any(entry =>
                                                                   entry.ReceiptHandle == message.ReceiptHandle
                                                                   )
                                                   ),
                    Any <CancellationToken>()
                    );
            }
            public async Task ShouldNotDeleteMessagesThatHaveBeenCanceled(
                RequestMessage message1,
                RequestMessage message2,
                HttpStatusCode statusCode,
                [Frozen] RequestOptions options,
                [Frozen, Substitute] IAmazonSQS sqs,
                [Target] SqsRequestMessageRelay relay,
                CancellationToken cancellationToken
                )
            {
                var task2CancellationTokenSource = new CancellationTokenSource();

                task2CancellationTokenSource.CancelAfter(1);

                var task1 = relay.Complete(message1, statusCode, null, cancellationToken);
                var task2 = relay.Complete(message2, statusCode, null, task2CancellationTokenSource.Token);

                Func <Task> func = () => Task.WhenAll(task1, task2);

                await func.Should().ThrowAsync <OperationCanceledException>();

                await sqs.Received().DeleteMessageBatchAsync(
                    Any <DeleteMessageBatchRequest>(),
                    Any <CancellationToken>()
                    );

                var batchRequest = (from call in sqs.ReceivedCalls()
                                    let arg = (DeleteMessageBatchRequest)call.GetArguments()[0]
                                              where arg.Entries.Any()
                                              select arg).First();

                batchRequest.QueueUrl.Should().Be(options.QueueUrl.ToString());
                batchRequest.Entries.Should().Contain(entry =>
                                                      entry.Id == message1.RequestDetails.Id.ToString() &&
                                                      entry.ReceiptHandle == message1.ReceiptHandle
                                                      );
                batchRequest.Entries.Should().NotContain(entry =>
                                                         entry.Id == message2.RequestDetails.Id.ToString() &&
                                                         entry.ReceiptHandle == message2.ReceiptHandle
                                                         );
            }