Refactor: Standardize method names across clients

Renamed methods across multiple client classes for consistency,
shortening and aligning naming conventions (e.g., `CheckAttachmentsAsync` → `CheckAsync`, `ValidatePdfAsync` → `ValidateAsync`).

Updated corresponding interfaces, unit tests, and documentation
to reflect the new method names. Standardized method signatures
to support both `Stream` and `byte[]` overloads consistently.

Improved error handling in tests and updated examples in the
README for batch processing and validation scenarios. Enhanced
API endpoint overview for clarity.
This commit is contained in:
2026-08-31 03:40:43 +02:00
parent f51fde6a23
commit 189622c476
18 changed files with 262 additions and 262 deletions

View File

@@ -84,20 +84,20 @@ public class WorkflowsClientTests
{
// Arrange
var pdfBytes = ValidPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
.ReturnsAsync(QrResult());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes);
var result = await Sut.ExtractSwissQrCodeAsync(pdfBytes);
// Assert
result.Should().NotBeNull();
result!.Bill.Should().NotBeNull();
result.Bill!.Currency.Should().Be("CHF");
_validation.Verify(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, It.IsAny<CancellationToken>()), Times.Once);
_validation.Verify(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(pdfBytes, false, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
@@ -105,18 +105,18 @@ public class WorkflowsClientTests
{
// Arrange
var pdfBytes = QrPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, true, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, true, It.IsAny<CancellationToken>()))
.ReturnsAsync(RawQrResult());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, raw: true);
var result = await Sut.ExtractSwissQrCodeAsync(pdfBytes, raw: true);
// Assert
result.Should().NotBeNull();
result!.RawLines.Should().Contain("SPC");
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(pdfBytes, true, It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(pdfBytes, true, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
@@ -124,16 +124,16 @@ public class WorkflowsClientTests
{
// Arrange
var pdfBytes = EncryptedPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
// Act
var act = async () => await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: true);
var act = async () => await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: true);
// Assert
await act.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("*PDF validation failed*");
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
@@ -141,15 +141,15 @@ public class WorkflowsClientTests
{
// Arrange
var pdfBytes = EncryptedPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: false);
var result = await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: false);
// Assert
result.Should().BeNull();
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
@@ -157,11 +157,11 @@ public class WorkflowsClientTests
{
// Arrange – PageCount=0 and FileSize=0 → IsValid=false
var pdfBytes = new byte[] { 0x00 };
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_EmptyFile());
// Act & Assert
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: true))
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: true))
.Should().ThrowAsync<InvalidOperationException>();
}
@@ -170,11 +170,11 @@ public class WorkflowsClientTests
{
// Arrange – ensure the message includes diagnostic fields
var pdfBytes = ValidPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
// Act
var act = async () => await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: true);
var act = async () => await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: true);
// Assert
var ex = await act.Should().ThrowAsync<InvalidOperationException>();
@@ -186,14 +186,14 @@ public class WorkflowsClientTests
{
// Arrange – simulate network/API failure during validation
var pdfBytes = ValidPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ThrowsAsync(new HttpRequestException("API unreachable"));
// Act & Assert
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfBytes))
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfBytes))
.Should().ThrowAsync<HttpRequestException>()
.WithMessage("*API unreachable*");
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
@@ -201,13 +201,13 @@ public class WorkflowsClientTests
{
// Arrange – validation succeeds but extraction fails
var pdfBytes = QrPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, false, It.IsAny<CancellationToken>()))
.ThrowsAsync(new HttpRequestException("Extraction failed"));
// Act & Assert
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfBytes))
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfBytes))
.Should().ThrowAsync<HttpRequestException>()
.WithMessage("*Extraction failed*");
}
@@ -219,15 +219,15 @@ public class WorkflowsClientTests
var pdfBytes = ValidPdfBytes();
var cts = new CancellationTokenSource();
var token = cts.Token;
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, token)).ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, token)).ReturnsAsync(QrResult());
_validation.Setup(v => v.ValidateAsync(pdfBytes, token)).ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractAsync(pdfBytes, false, token)).ReturnsAsync(QrResult());
// Act
await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, cancellationToken: token);
await Sut.ExtractSwissQrCodeAsync(pdfBytes, cancellationToken: token);
// Assert
_validation.Verify(v => v.ValidatePdfAsync(pdfBytes, token), Times.Once);
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(pdfBytes, false, token), Times.Once);
_validation.Verify(v => v.ValidateAsync(pdfBytes, token), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(pdfBytes, false, token), Times.Once);
}
// ═════════════════════════════════════════════════════════════════════════
@@ -238,20 +238,20 @@ public class WorkflowsClientTests
public async Task Stream_ValidPdf_CallsValidationWithStreamThenExtractionWithStream_ReturnsResult()
{
// Arrange – validation client receives a Stream, extraction client receives the same stream reset to 0
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
.ReturnsAsync(QrResult());
using var pdfStream = new MemoryStream(ValidPdfBytes());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream);
var result = await Sut.ExtractSwissQrCodeAsync(pdfStream);
// Assert
result.Should().NotBeNull();
_validation.Verify(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()), Times.Once);
_validation.Verify(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
@@ -259,16 +259,16 @@ public class WorkflowsClientTests
{
// Arrange – we verify the stream position is 0 when extraction is called
Stream? streamAtExtraction = null;
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<Stream>(), false, It.IsAny<CancellationToken>()))
.Callback<Stream, bool, CancellationToken>((s, _, _) => streamAtExtraction = s)
.ReturnsAsync(QrResult());
using var pdfStream = new MemoryStream(ValidPdfBytes());
// Act
await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream);
await Sut.ExtractSwissQrCodeAsync(pdfStream);
// Assert
streamAtExtraction.Should().NotBeNull();
@@ -279,52 +279,52 @@ public class WorkflowsClientTests
public async Task Stream_InvalidPdf_ThrowIfInvalidTrue_ThrowsWithoutCallingExtraction()
{
// Arrange
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
using var pdfStream = new MemoryStream(EncryptedPdfBytes());
// Act & Assert
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(pdfStream, throwIfInvalid: true))
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(pdfStream, throwIfInvalid: true))
.Should().ThrowAsync<InvalidOperationException>()
.WithMessage("*PDF validation failed*");
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
public async Task Stream_InvalidPdf_ThrowIfInvalidFalse_ReturnsNull()
{
// Arrange
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
using var pdfStream = new MemoryStream(EncryptedPdfBytes());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream, throwIfInvalid: false);
var result = await Sut.ExtractSwissQrCodeAsync(pdfStream, throwIfInvalid: false);
// Assert
result.Should().BeNull();
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
public async Task Stream_ValidPdf_RawMode_PassesRawFlagToExtraction()
{
// Arrange
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<Stream>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()))
.ReturnsAsync(RawQrResult());
using var pdfStream = new MemoryStream(QrPdfBytes());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(pdfStream, raw: true);
var result = await Sut.ExtractSwissQrCodeAsync(pdfStream, raw: true);
// Assert
result.Should().NotBeNull();
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<Stream>(), true, It.IsAny<CancellationToken>()), Times.Once);
}
// ═════════════════════════════════════════════════════════════════════════
@@ -340,18 +340,18 @@ public class WorkflowsClientTests
{
await File.WriteAllBytesAsync(tempPath, ValidPdfBytes());
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()))
.ReturnsAsync(QrResult());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(tempPath);
var result = await Sut.ExtractSwissQrCodeAsync(tempPath);
// Assert
result.Should().NotBeNull();
_validation.Verify(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()), Times.Once);
_validation.Verify(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), false, It.IsAny<CancellationToken>()), Times.Once);
}
finally
{
@@ -368,13 +368,13 @@ public class WorkflowsClientTests
{
await File.WriteAllBytesAsync(tempPath, EncryptedPdfBytes());
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
// Act & Assert
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(tempPath, throwIfInvalid: true))
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(tempPath, throwIfInvalid: true))
.Should().ThrowAsync<InvalidOperationException>();
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
finally
{
@@ -391,11 +391,11 @@ public class WorkflowsClientTests
{
await File.WriteAllBytesAsync(tempPath, EncryptedPdfBytes());
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(tempPath, throwIfInvalid: false);
var result = await Sut.ExtractSwissQrCodeAsync(tempPath, throwIfInvalid: false);
// Assert
result.Should().BeNull();
@@ -413,10 +413,10 @@ public class WorkflowsClientTests
var nonExistent = Path.Combine(Path.GetTempPath(), "does_not_exist_12345.pdf");
// Act & Assert
await Sut.Invoking(s => s.ExtractSwissQrCodeValidatedAsync(nonExistent))
await Sut.Invoking(s => s.ExtractSwissQrCodeAsync(nonExistent))
.Should().ThrowAsync<FileNotFoundException>();
_validation.Verify(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
_validation.Verify(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()), Times.Never);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Fact]
@@ -428,17 +428,17 @@ public class WorkflowsClientTests
{
await File.WriteAllBytesAsync(tempPath, QrPdfBytes());
_validation.Setup(v => v.ValidatePdfAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(It.IsAny<byte[]>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(ValidResult());
_swissQrCode.Setup(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()))
_swissQrCode.Setup(q => q.ExtractAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()))
.ReturnsAsync(RawQrResult());
// Act
var result = await Sut.ExtractSwissQrCodeValidatedAsync(tempPath, raw: true);
var result = await Sut.ExtractSwissQrCodeAsync(tempPath, raw: true);
// Assert
result.Should().NotBeNull();
_swissQrCode.Verify(q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()), Times.Once);
_swissQrCode.Verify(q => q.ExtractAsync(It.IsAny<byte[]>(), true, It.IsAny<CancellationToken>()), Times.Once);
}
finally
{
@@ -457,16 +457,16 @@ public class WorkflowsClientTests
{
// Arrange
var pdfBytes = EncryptedPdfBytes();
_validation.Setup(v => v.ValidatePdfAsync(pdfBytes, It.IsAny<CancellationToken>()))
_validation.Setup(v => v.ValidateAsync(pdfBytes, It.IsAny<CancellationToken>()))
.ReturnsAsync(InvalidResult_Encrypted());
// Act
try { await Sut.ExtractSwissQrCodeValidatedAsync(pdfBytes, throwIfInvalid: throwIfInvalid); }
try { await Sut.ExtractSwissQrCodeAsync(pdfBytes, throwIfInvalid: throwIfInvalid); }
catch (InvalidOperationException) { /* expected when throwIfInvalid=true */ }
// Assert — extraction must never be called in either branch
_swissQrCode.Verify(
q => q.ExtractSwissQrCodeAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
q => q.ExtractAsync(It.IsAny<byte[]>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()),
Times.Never,
"extraction must not be attempted on an invalid document");
}