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

@@ -54,10 +54,10 @@ public class PdfAttachmentClientTests
return ms.ToArray();
}
// ?? CheckAttachmentsAsync (Stream) ???????????????????????????????????????
// ?? CheckAsync (Stream) ???????????????????????????????????????
[Fact]
public async Task CheckAttachmentsAsync_Stream_SendsMultipartPost()
public async Task CheckAsync_Stream_SendsMultipartPost()
{
// Arrange
var expected = new AttachmentCheckResult
@@ -72,7 +72,7 @@ public class PdfAttachmentClientTests
var (client, handler) = BuildJson(expected);
// Act
var result = await client.CheckAttachmentsAsync(new MemoryStream(FakePdfBytes()));
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.HasAttachments.Should().BeTrue();
@@ -83,14 +83,14 @@ public class PdfAttachmentClientTests
}
[Fact]
public async Task CheckAttachmentsAsync_Stream_PdfWithNoAttachments_ReturnsFalse()
public async Task CheckAsync_Stream_PdfWithNoAttachments_ReturnsFalse()
{
// Arrange
var expected = new AttachmentCheckResult { HasAttachments = false, AttachmentCount = 0, Attachments = [] };
var (client, _) = BuildJson(expected);
// Act
var result = await client.CheckAttachmentsAsync(new MemoryStream(FakePdfBytes()));
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.HasAttachments.Should().BeFalse();
@@ -98,17 +98,17 @@ public class PdfAttachmentClientTests
result.Attachments.Should().BeEmpty();
}
// ?? CheckAttachmentsAsync (byte[]) ???????????????????????????????????????
// ?? CheckAsync (byte[]) ???????????????????????????????????????
[Fact]
public async Task CheckAttachmentsAsync_Bytes_SendsJsonWithBase64()
public async Task CheckAsync_Bytes_SendsJsonWithBase64()
{
// Arrange
var expected = new AttachmentCheckResult { HasAttachments = false };
var (client, handler) = BuildJson(expected);
// Act
await client.CheckAttachmentsAsync(FakePdfBytes());
await client.CheckAsync(FakePdfBytes());
// Assert
handler.LastRequest!.Content.Should().NotBeNull();
@@ -118,10 +118,10 @@ public class PdfAttachmentClientTests
doc.RootElement.GetProperty("base64Pdf").GetString().Should().NotBeNullOrEmpty();
}
// ?? ExtractAttachmentsAsync (Stream) <20> ZIP unzip ?????????????????????????
// ?? ExtractAsync (Stream) <20> ZIP unzip ?????????????????????????
[Fact]
public async Task ExtractAttachmentsAsync_Stream_UnzipsAndReturnsDictionary()
public async Task ExtractAsync_Stream_UnzipsAndReturnsDictionary()
{
// Arrange
var zipBytes = BuildZip(new Dictionary<string, string>
@@ -132,7 +132,7 @@ public class PdfAttachmentClientTests
var (client, handler) = BuildBytes(zipBytes);
// Act
var result = await client.ExtractAttachmentsAsync(new MemoryStream(FakePdfBytes()));
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.Should().HaveCount(2);
@@ -150,7 +150,7 @@ public class PdfAttachmentClientTests
}
[Fact]
public async Task ExtractAttachmentsAsync_Stream_WithSingleEntry_ReturnsOneItem()
public async Task ExtractAsync_Stream_WithSingleEntry_ReturnsOneItem()
{
// Arrange
var zipBytes = BuildZip(new Dictionary<string, string>
@@ -160,7 +160,7 @@ public class PdfAttachmentClientTests
var (client, _) = BuildBytes(zipBytes);
// Act
var result = await client.ExtractAttachmentsAsync(new MemoryStream(FakePdfBytes()));
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.Should().HaveCount(1);
@@ -169,10 +169,10 @@ public class PdfAttachmentClientTests
foreach (var s in result.Values) s.Dispose();
}
// ?? ExtractAttachmentsAsync (byte[]) <20> ZIP unzip ?????????????????????????
// ?? ExtractAsync (byte[]) <20> ZIP unzip ?????????????????????????
[Fact]
public async Task ExtractAttachmentsAsync_Bytes_SendsJsonAndUnzips()
public async Task ExtractAsync_Bytes_SendsJsonAndUnzips()
{
// Arrange
var zipBytes = BuildZip(new Dictionary<string, string>
@@ -182,7 +182,7 @@ public class PdfAttachmentClientTests
var (client, handler) = BuildBytes(zipBytes);
// Act
var result = await client.ExtractAttachmentsAsync(FakePdfBytes());
var result = await client.ExtractAsync(FakePdfBytes());
// Assert
result.Should().ContainKey("invoice.xml");
@@ -195,7 +195,7 @@ public class PdfAttachmentClientTests
// ?? HTTP error propagation ???????????????????????????????????????????????
[Fact]
public async Task CheckAttachmentsAsync_WhenApiReturns404_ThrowsHttpRequestException()
public async Task CheckAsync_WhenApiReturns404_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.NotFound);
@@ -203,12 +203,12 @@ public class PdfAttachmentClientTests
var client = new PdfAttachmentClient(httpClient, NullLogger<PdfAttachmentClient>.Instance);
// Act & Assert
await client.Invoking(c => c.CheckAttachmentsAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.CheckAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
[Fact]
public async Task ExtractAttachmentsAsync_WhenApiReturns500_ThrowsHttpRequestException()
public async Task ExtractAsync_WhenApiReturns500_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError);
@@ -216,7 +216,7 @@ public class PdfAttachmentClientTests
var client = new PdfAttachmentClient(httpClient, NullLogger<PdfAttachmentClient>.Instance);
// Act & Assert
await client.Invoking(c => c.ExtractAttachmentsAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.ExtractAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
}

View File

@@ -28,15 +28,15 @@ public class PdfValidationClientTests
private static byte[] FakePdfBytes() => "fake-pdf"u8.ToArray();
// ── ValidatePdfAsync (Stream) ────────────────────────────────────────────
// ── ValidateAsync (Stream) ────────────────────────────────────────────
[Fact]
public async Task ValidatePdfAsync_Stream_SendsMultipartPost()
public async Task ValidateAsync_Stream_SendsMultipartPost()
{
var expected = new PdfValidationResult(PageCount: 3, FileSizeBytes: 2048, FileSizeMB: 0, PdfVersion: "1.7", HasAttachments: false, AttachmentCount: 0, IsEncrypted: false);
var (client, handler) = Build(expected);
var result = await client.ValidatePdfAsync(new MemoryStream(FakePdfBytes()));
var result = await client.ValidateAsync(new MemoryStream(FakePdfBytes()));
result.PageCount.Should().Be(3);
result.PdfVersion.Should().Be("1.7");
@@ -48,52 +48,52 @@ public class PdfValidationClientTests
}
[Fact]
public async Task ValidatePdfAsync_Stream_EncryptedPdf_DeserializesIsEncryptedTrue()
public async Task ValidateAsync_Stream_EncryptedPdf_DeserializesIsEncryptedTrue()
{
var expected = new PdfValidationResult(PageCount: 1, FileSizeBytes: 0, FileSizeMB: 0, PdfVersion: "1.6", HasAttachments: false, AttachmentCount: 0, IsEncrypted: true);
var (client, _) = Build(expected);
var result = await client.ValidatePdfAsync(new MemoryStream(FakePdfBytes()));
var result = await client.ValidateAsync(new MemoryStream(FakePdfBytes()));
result.IsEncrypted.Should().BeTrue("encrypted PDFs should surface IsEncrypted=true");
}
[Fact]
public async Task ValidatePdfAsync_Stream_ThrowsWhenApiReturnsNull()
public async Task ValidateAsync_Stream_ThrowsWhenApiReturnsNull()
{
var handler = MockHttpMessageHandler.ReturningJson<PdfValidationResult?>(null);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new PdfValidationClient(httpClient, NullLogger<PdfValidationClient>.Instance);
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.ValidateAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<InvalidOperationException>();
}
[Fact]
public async Task ValidatePdfAsync_Stream_WhenApiReturns400_ThrowsHttpRequestException()
public async Task ValidateAsync_Stream_WhenApiReturns400_ThrowsHttpRequestException()
{
var (client, _) = BuildError(HttpStatusCode.BadRequest);
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.ValidateAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
[Fact]
public async Task ValidatePdfAsync_Stream_WhenApiReturns500_ThrowsHttpRequestException()
public async Task ValidateAsync_Stream_WhenApiReturns500_ThrowsHttpRequestException()
{
var (client, _) = BuildError(HttpStatusCode.InternalServerError);
await client.Invoking(c => c.ValidatePdfAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.ValidateAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
// ── ValidatePdfAsync (byte[]) ────────────────────────────────────────────
// ── ValidateAsync (byte[]) ────────────────────────────────────────────
[Fact]
public async Task ValidatePdfAsync_Bytes_SendsJsonWithBase64()
public async Task ValidateAsync_Bytes_SendsJsonWithBase64()
{
var expected = new PdfValidationResult(PageCount: 1, FileSizeBytes: 0, FileSizeMB: 0, PdfVersion: "", HasAttachments: true, AttachmentCount: 2, IsEncrypted: false);
var (client, handler) = Build(expected);
var result = await client.ValidatePdfAsync(FakePdfBytes());
var result = await client.ValidateAsync(FakePdfBytes());
result.PageCount.Should().Be(1);
result.HasAttachments.Should().BeTrue();
@@ -105,10 +105,10 @@ public class PdfValidationClientTests
}
[Fact]
public async Task ValidatePdfAsync_Bytes_WhenApiReturns400_ThrowsHttpRequestException()
public async Task ValidateAsync_Bytes_WhenApiReturns400_ThrowsHttpRequestException()
{
var (client, _) = BuildError(HttpStatusCode.BadRequest);
await client.Invoking(c => c.ValidatePdfAsync(FakePdfBytes()))
await client.Invoking(c => c.ValidateAsync(FakePdfBytes()))
.Should().ThrowAsync<HttpRequestException>();
}

View File

@@ -11,7 +11,7 @@ namespace DocumentService.Tests.Unit.Client;
/// <summary>
/// Unit tests for <see cref="SwissQrCodeClient"/>.
/// All tests use a fake <see cref="MockHttpMessageHandler"/> — no real HTTP calls are made.
/// All tests use a fake <see cref="MockHttpMessageHandler"/> <EFBFBD> no real HTTP calls are made.
/// </summary>
public class SwissQrCodeClientTests
{
@@ -27,10 +27,10 @@ public class SwissQrCodeClientTests
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
// ?? ExtractSwissQrCodeAsync (Stream) — parsed Bill ??????????????????????
// ?? ExtractAsync (Stream) <EFBFBD> parsed Bill ??????????????????????
[Fact]
public async Task ExtractSwissQrCodeAsync_Stream_ParsedMode_SendsMultipartToCorrectEndpoint()
public async Task ExtractAsync_Stream_ParsedMode_SendsMultipartToCorrectEndpoint()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(
@@ -47,7 +47,7 @@ public class SwissQrCodeClientTests
var (client, handler) = Build(expected);
// Act
var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: false);
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()), raw: false);
// Assert
result.Should().NotBeNull();
@@ -56,31 +56,31 @@ public class SwissQrCodeClientTests
}
[Fact]
public async Task ExtractSwissQrCodeAsync_Stream_RawMode_SendsRawFlagInUrl()
public async Task ExtractAsync_Stream_RawMode_SendsRawFlagInUrl()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC", "0200", "1"]);
var (client, handler) = Build(expected);
// Act
var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: true);
var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()), raw: true);
// Assert
result.RawLines.Should().HaveCount(3).And.StartWith("SPC");
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True");
}
// ?? ExtractSwissQrCodeAsync (byte[]) ????????????????????????????????????
// ?? ExtractAsync (byte[]) ????????????????????????????????????
[Fact]
public async Task ExtractSwissQrCodeAsync_Bytes_SendsJsonWithBase64()
public async Task ExtractAsync_Bytes_SendsJsonWithBase64()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: []);
var (client, handler) = Build(expected);
// Act
await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: false);
await client.ExtractAsync(FakePdfBytes(), raw: false);
// Assert
handler.LastRequest!.Content.Should().NotBeNull();
@@ -91,14 +91,14 @@ public class SwissQrCodeClientTests
}
[Fact]
public async Task ExtractSwissQrCodeAsync_Bytes_RawMode_IncludesRawFlagInUrl()
public async Task ExtractAsync_Bytes_RawMode_IncludesRawFlagInUrl()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC"]);
var (client, handler) = Build(expected);
// Act
await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: true);
await client.ExtractAsync(FakePdfBytes(), raw: true);
// Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True");
@@ -107,7 +107,7 @@ public class SwissQrCodeClientTests
// ?? HTTP error propagation ??????????????????????????????????????????????
[Fact]
public async Task ExtractSwissQrCodeAsync_WhenApiReturns404_ThrowsHttpRequestException()
public async Task ExtractAsync_WhenApiReturns404_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.NotFound);
@@ -115,12 +115,12 @@ public class SwissQrCodeClientTests
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
// Act & Assert
await client.Invoking(c => c.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.ExtractAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
[Fact]
public async Task ExtractSwissQrCodeAsync_WhenApiReturns500_ThrowsHttpRequestException()
public async Task ExtractAsync_WhenApiReturns500_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError);
@@ -128,7 +128,7 @@ public class SwissQrCodeClientTests
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
// Act & Assert
await client.Invoking(c => c.ExtractSwissQrCodeAsync(FakePdfBytes()))
await client.Invoking(c => c.ExtractAsync(FakePdfBytes()))
.Should().ThrowAsync<HttpRequestException>();
}
}

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");
}

View File

@@ -12,7 +12,7 @@ namespace DocumentService.Tests.Unit.Client;
/// <summary>
/// Unit tests for <see cref="ZugferdClient"/>.
/// All tests use a fake <see cref="MockHttpMessageHandler"/> — no real HTTP calls are made.
/// All tests use a fake <see cref="MockHttpMessageHandler"/> <EFBFBD> no real HTTP calls are made.
/// </summary>
public class ZugferdClientTests
{
@@ -37,17 +37,17 @@ public class ZugferdClientTests
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
private static byte[] FakeXmlBytes() => "<invoice>test</invoice>"u8.ToArray();
// ?? HasZugferdAsync (Stream) ?????????????????????????????????????????????
// ?? CheckAsync (Stream) ?????????????????????????????????????????????
[Fact]
public async Task HasZugferdAsync_Stream_WhenZugferdPresent_ReturnsTrue()
public async Task CheckAsync_Stream_WhenZugferdPresent_ReturnsTrue()
{
// Arrange
var expected = new ZugferdCheckResult { HasZugferd = true, ZugferdFileName = "factur-x.xml" };
var (client, handler) = BuildJson(expected);
// Act
var result = await client.HasZugferdAsync(new MemoryStream(FakePdfBytes()));
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.HasZugferd.Should().BeTrue();
@@ -56,31 +56,31 @@ public class ZugferdClientTests
}
[Fact]
public async Task HasZugferdAsync_Stream_WhenNoZugferd_ReturnsFalse()
public async Task CheckAsync_Stream_WhenNoZugferd_ReturnsFalse()
{
// Arrange
var expected = new ZugferdCheckResult { HasZugferd = false };
var (client, _) = BuildJson(expected);
// Act
var result = await client.HasZugferdAsync(new MemoryStream(FakePdfBytes()));
var result = await client.CheckAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.HasZugferd.Should().BeFalse();
result.ZugferdFileName.Should().BeNull();
}
// ?? HasZugferdAsync (byte[]) ?????????????????????????????????????????????
// ?? CheckAsync (byte[]) ?????????????????????????????????????????????
[Fact]
public async Task HasZugferdAsync_Bytes_SendsJsonWithBase64()
public async Task CheckAsync_Bytes_SendsJsonWithBase64()
{
// Arrange
var expected = new ZugferdCheckResult { HasZugferd = true };
var (client, handler) = BuildJson(expected);
// Act
await client.HasZugferdAsync(FakePdfBytes());
await client.CheckAsync(FakePdfBytes());
// Assert
handler.LastRequest!.Content.Should().NotBeNull();
@@ -90,16 +90,16 @@ public class ZugferdClientTests
doc.RootElement.GetProperty("base64Pdf").GetString().Should().NotBeNullOrEmpty();
}
// ?? ExtractZugferdAsync (Stream) — raw XML stream ?????????????????????????
// ?? ExtractAsync (Stream) <EFBFBD> raw XML stream ?????????????????????????
[Fact]
public async Task ExtractZugferdAsync_Stream_SendsMultipartWithAsFileTrue()
public async Task ExtractAsync_Stream_SendsMultipartWithAsFileTrue()
{
// Arrange
var (client, handler) = BuildBytes(FakeXmlBytes());
// Act
using var result = await client.ExtractZugferdAsync(new MemoryStream(FakePdfBytes()));
using var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.Should().NotBeNull();
@@ -108,30 +108,30 @@ public class ZugferdClientTests
}
[Fact]
public async Task ExtractZugferdAsync_Stream_ReturnsXmlContent()
public async Task ExtractAsync_Stream_ReturnsXmlContent()
{
// Arrange
var xmlBytes = "<root><invoice/></root>"u8.ToArray();
var (client, _) = BuildBytes(xmlBytes);
// Act
using var result = await client.ExtractZugferdAsync(new MemoryStream(FakePdfBytes()));
using var result = await client.ExtractAsync(new MemoryStream(FakePdfBytes()));
var content = await new StreamReader(result).ReadToEndAsync();
// Assert
content.Should().Be("<root><invoice/></root>");
}
// ?? ExtractZugferdAsync (byte[]) ?????????????????????????????????????????
// ?? ExtractAsync (byte[]) ?????????????????????????????????????????
[Fact]
public async Task ExtractZugferdAsync_Bytes_SendsJsonWithFormatFile()
public async Task ExtractAsync_Bytes_SendsJsonWithFormatFile()
{
// Arrange
var (client, handler) = BuildBytes(FakeXmlBytes());
// Act
using var result = await client.ExtractZugferdAsync(FakePdfBytes());
using var result = await client.ExtractAsync(FakePdfBytes());
// Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?format=file");
@@ -139,10 +139,10 @@ public class ZugferdClientTests
handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
}
// ?? ExtractZugferdAsResultAsync (Stream) ?????????????????????????????????
// ?? ExtractAsResultAsync (Stream) ?????????????????????????????????
[Fact]
public async Task ExtractZugferdAsResultAsync_Stream_ReturnsStructuredResult()
public async Task ExtractAsResultAsync_Stream_ReturnsStructuredResult()
{
// Arrange
var expected = new ZugferdExtractionResult
@@ -153,7 +153,7 @@ public class ZugferdClientTests
var (client, handler) = BuildJson(expected);
// Act
var result = await client.ExtractZugferdAsResultAsync(new MemoryStream(FakePdfBytes()));
var result = await client.ExtractAsResultAsync(new MemoryStream(FakePdfBytes()));
// Assert
result.FileName.Should().Be("factur-x.xml");
@@ -161,17 +161,17 @@ public class ZugferdClientTests
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?asFile=false");
}
// ?? ExtractZugferdAsResultAsync (byte[]) ?????????????????????????????????
// ?? ExtractAsResultAsync (byte[]) ?????????????????????????????????
[Fact]
public async Task ExtractZugferdAsResultAsync_Bytes_SendsJsonWithFormatJson()
public async Task ExtractAsResultAsync_Bytes_SendsJsonWithFormatJson()
{
// Arrange
var expected = new ZugferdExtractionResult { FileName = "zugferd.xml", XmlContent = "<x/>" };
var (client, handler) = BuildJson(expected);
// Act
await client.ExtractZugferdAsResultAsync(FakePdfBytes());
await client.ExtractAsResultAsync(FakePdfBytes());
// Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/zugferd/extract?format=json");
@@ -182,7 +182,7 @@ public class ZugferdClientTests
// ?? HTTP error propagation ???????????????????????????????????????????????
[Fact]
public async Task HasZugferdAsync_WhenApiReturns400_ThrowsHttpRequestException()
public async Task CheckAsync_WhenApiReturns400_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.BadRequest);
@@ -190,7 +190,7 @@ public class ZugferdClientTests
var client = new ZugferdClient(httpClient, NullLogger<ZugferdClient>.Instance);
// Act & Assert
await client.Invoking(c => c.HasZugferdAsync(new MemoryStream(FakePdfBytes())))
await client.Invoking(c => c.CheckAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
}