Files
DocumentService/DocumentService.Tests/Unit/Client/SwissQrCodeClientTests.cs
TekH 75bea9ef29 Refactor DTOs and tests; add framework-specific handling
Refactored the codebase to use shared DTOs from `DocumentService.Application.Common.DTOs`, removing inline DTO definitions in client interfaces and tests. Introduced conditional compilation to handle framework-specific differences in DTOs and handlers.

Updated test cases to align with the new DTO structures, including `SwissQrCodeExtractionResult`, `PdfValidationResult`, and `ZugferdExtractionResult`. Adjusted test data to match updated DTO properties.

Cleaned up solution and project files, ensuring proper references and organization. Removed unused files and fixed project references in `DocumentService.Tests.csproj`. Improved maintainability and consistency across the codebase.
2026-08-31 00:54:38 +02:00

135 lines
5.2 KiB
C#

using DocumentService.Application.Common.DTOs;
using DocumentService.Client.Clients;
using DocumentService.Client.Interfaces;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using System.Net;
using System.Net.Http;
using System.Text.Json;
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.
/// </summary>
public class SwissQrCodeClientTests
{
// ?? helpers ????????????????????????????????????????????????????????????
private static (SwissQrCodeClient client, MockHttpMessageHandler handler) Build<T>(T body)
{
var handler = MockHttpMessageHandler.ReturningJson(body);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
return (client, handler);
}
private static byte[] FakePdfBytes() => "fake-pdf-content"u8.ToArray();
// ?? ExtractSwissQrCodeAsync (Stream) — parsed Bill ??????????????????????
[Fact]
public async Task ExtractSwissQrCodeAsync_Stream_ParsedMode_SendsMultipartToCorrectEndpoint()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(
Bill: new SwissQrBillDto
{
Version = "V2_0",
Currency = "CHF",
Account = "CH9300762011623852957",
Creditor = new AddressDto { Name = "Test AG", Town = "Bern", CountryCode = "CH", Type = "S", PostalCode = "3000" },
ReferenceType = "NON"
},
RawLines: []
);
var (client, handler) = Build(expected);
// Act
var result = await client.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes()), raw: false);
// Assert
result.Should().NotBeNull();
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=False");
handler.LastRequest.Content.Should().BeOfType<MultipartFormDataContent>();
}
[Fact]
public async Task ExtractSwissQrCodeAsync_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);
// 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[]) ????????????????????????????????????
[Fact]
public async Task ExtractSwissQrCodeAsync_Bytes_SendsJsonWithBase64()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: []);
var (client, handler) = Build(expected);
// Act
await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: false);
// Assert
handler.LastRequest!.Content.Should().NotBeNull();
handler.LastRequest.Content!.Headers.ContentType!.MediaType.Should().Be("application/json");
var body = await handler.LastRequest.Content!.ReadAsStringAsync();
var doc = JsonDocument.Parse(body);
doc.RootElement.GetProperty("base64Pdf").GetString().Should().NotBeNullOrEmpty();
}
[Fact]
public async Task ExtractSwissQrCodeAsync_Bytes_RawMode_IncludesRawFlagInUrl()
{
// Arrange
var expected = new SwissQrCodeExtractionResult(Bill: null, RawLines: ["SPC"]);
var (client, handler) = Build(expected);
// Act
await client.ExtractSwissQrCodeAsync(FakePdfBytes(), raw: true);
// Assert
handler.LastRequest!.RequestUri!.PathAndQuery.Should().Be("/api/pdf/qr-code/extract-swiss?raw=True");
}
// ?? HTTP error propagation ??????????????????????????????????????????????
[Fact]
public async Task ExtractSwissQrCodeAsync_WhenApiReturns404_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.NotFound);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
// Act & Assert
await client.Invoking(c => c.ExtractSwissQrCodeAsync(new MemoryStream(FakePdfBytes())))
.Should().ThrowAsync<HttpRequestException>();
}
[Fact]
public async Task ExtractSwissQrCodeAsync_WhenApiReturns500_ThrowsHttpRequestException()
{
// Arrange
var handler = MockHttpMessageHandler.ReturningStatus(HttpStatusCode.InternalServerError);
var httpClient = new HttpClient(handler) { BaseAddress = new Uri("http://localhost") };
var client = new SwissQrCodeClient(httpClient, NullLogger<SwissQrCodeClient>.Instance);
// Act & Assert
await client.Invoking(c => c.ExtractSwissQrCodeAsync(FakePdfBytes()))
.Should().ThrowAsync<HttpRequestException>();
}
}