test(unit): migrate unit tests to Stream API
Application Handler Tests: - ValidatePdfHandlerTests: PdfStream = new MemoryStream(pdfBytes) - ValidatePdfAQueryHandlerTests: PdfStream = new MemoryStream(pdfBytes) - CheckPdfAttachmentsQueryHandlerTests: PdfStream = new MemoryStream(pdfBytes) - Remove Base64/PdfBytes property usage Infrastructure Tests: - DevExpressSwissQrCodeProcessorTests: LoadTestPdf() returns Stream - All test methods use 'using var stream' pattern - Add test: ExtractSwissQrCodeAsync_StreamNotAtBeginning_ThrowsBadRequestException Result: All unit tests pass with Stream-based API
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using System.Reflection;
|
||||
using DocumentOperator.Application.Common.Interfaces;
|
||||
using DocumentOperator.Domain.Common.Exceptions;
|
||||
using DocumentOperator.Domain.Exceptions;
|
||||
using DocumentOperator.Infrastructure.Services.QrCodeProcessing;
|
||||
using FluentAssertions;
|
||||
|
||||
@@ -24,16 +23,16 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
#region Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Loads a test PDF from embedded resources.
|
||||
/// Loads a test PDF from embedded resources as a Stream.
|
||||
/// </summary>
|
||||
/// <param name="filename">Name of the PDF file (e.g., "pdfWithSwissQRCode.pdf")</param>
|
||||
/// <returns>PDF content as byte array</returns>
|
||||
private static byte[] LoadTestPdf(string filename)
|
||||
/// <returns>PDF content as MemoryStream</returns>
|
||||
private static Stream LoadTestPdf(string filename)
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
var resourceName = $"DocumentOperator.Tests.TestData.Pdfs.{filename}";
|
||||
|
||||
using var stream = assembly.GetManifestResourceStream(resourceName);
|
||||
var stream = assembly.GetManifestResourceStream(resourceName);
|
||||
|
||||
if (stream == null)
|
||||
{
|
||||
@@ -42,9 +41,11 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
$"Available resources: {string.Join(", ", assembly.GetManifestResourceNames())}");
|
||||
}
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
// Copy to MemoryStream so caller can reuse/seek
|
||||
var memoryStream = new MemoryStream();
|
||||
stream.CopyTo(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
memoryStream.Position = 0; // Reset position for reading
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -55,10 +56,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_PdfWithSwissQrCode_ReturnsQrCodeData()
|
||||
{
|
||||
// Arrange
|
||||
byte[] pdfBytes = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
using var pdfStream = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
|
||||
// Act
|
||||
var (bill, rawLines) = await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var (bill, rawLines) = await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
bill.Should().NotBeNull("PDF contains a Swiss QR Code");
|
||||
@@ -73,10 +74,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_PdfWithSwissQrCode_ReturnsValidIban()
|
||||
{
|
||||
// Arrange
|
||||
byte[] pdfBytes = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
using var pdfStream = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
|
||||
// Act
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
bill.Account.Should().MatchRegex(@"^CH\d{2}[A-Z0-9]{17}$",
|
||||
@@ -87,10 +88,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_PdfWithSwissQrCode_ReturnsCurrency()
|
||||
{
|
||||
// Arrange
|
||||
byte[] pdfBytes = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
using var pdfStream = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
|
||||
// Act
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
bill.Currency.Should().BeOneOf("CHF", "EUR",
|
||||
@@ -101,10 +102,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_PdfWithoutQrCode_ThrowsSwissQrCodeNotFoundException()
|
||||
{
|
||||
// Arrange: valid.pdf doesn't contain a Swiss QR Code
|
||||
byte[] pdfBytes = LoadTestPdf("valid.pdf");
|
||||
using var pdfStream = LoadTestPdf("valid.pdf");
|
||||
|
||||
// Act & Assert
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
await act.Should().ThrowAsync<NotFoundException>()
|
||||
.WithMessage("*No valid Swiss QR Code found*");
|
||||
@@ -113,11 +114,11 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_EmptyPdf_ThrowsException()
|
||||
{
|
||||
// Arrange: Empty byte array
|
||||
byte[] emptyPdfBytes = [];
|
||||
// Arrange: Empty stream
|
||||
using var emptyStream = new MemoryStream();
|
||||
|
||||
// Act & Assert
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(emptyPdfBytes);
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(emptyStream);
|
||||
|
||||
await act.Should().ThrowAsync<Exception>()
|
||||
.Where(ex => ex is ArgumentException);
|
||||
@@ -127,26 +128,40 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_NullInput_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange
|
||||
byte[] nullPdfBytes = null!;
|
||||
Stream nullStream = null!;
|
||||
|
||||
// Act & Assert
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(nullPdfBytes);
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(nullStream);
|
||||
|
||||
await act.Should().ThrowAsync<NullReferenceException>();
|
||||
await act.Should().ThrowAsync<ArgumentNullException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_InvalidPdfBytes_ThrowsPdfProcessingException()
|
||||
{
|
||||
// Arrange: Random bytes that are not a valid PDF
|
||||
byte[] invalidPdfBytes = "This is not a PDF file"u8.ToArray();
|
||||
using var invalidStream = new MemoryStream("This is not a PDF file"u8.ToArray());
|
||||
|
||||
// Act & Assert
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(invalidPdfBytes);
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(invalidStream);
|
||||
|
||||
await act.Should().ThrowAsync<ArgumentException>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractSwissQrCodeAsync_StreamNotAtBeginning_ThrowsArgumentException()
|
||||
{
|
||||
// Arrange: Valid PDF but stream position is not at 0
|
||||
using var pdfStream = LoadTestPdf("valid.pdf");
|
||||
pdfStream.Position = 10; // Move position away from beginning
|
||||
|
||||
// Act & Assert
|
||||
var act = async () => await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
await act.Should().ThrowAsync<ArgumentException>()
|
||||
.WithMessage("*Position = 0*");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Swiss QR Code Content Validation Tests
|
||||
@@ -155,10 +170,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_ValidQrCode_ParsesCreditorInformation()
|
||||
{
|
||||
// Arrange
|
||||
byte[] pdfBytes = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
using var pdfStream = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
|
||||
// Act
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
bill.Creditor.Should().NotBeNull("Creditor information is required");
|
||||
@@ -170,10 +185,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_ValidQrCode_ParsesDebtorInformationIfPresent()
|
||||
{
|
||||
// Arrange
|
||||
byte[] pdfBytes = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
using var pdfStream = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
|
||||
// Act
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
// Debtor information is OPTIONAL in Swiss QR Bill Standard 2.0
|
||||
@@ -190,10 +205,10 @@ public class DevExpressSwissQrCodeProcessorTests
|
||||
public async Task ExtractSwissQrCodeAsync_ValidQrCode_ParsesAmountIfPresent()
|
||||
{
|
||||
// Arrange
|
||||
byte[] pdfBytes = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
using var pdfStream = LoadTestPdf("pdfWithSwissQRCode.pdf");
|
||||
|
||||
// Act
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfBytes);
|
||||
var (bill, _) = await _sut.ExtractSwissQrCodeAsync(pdfStream);
|
||||
|
||||
// Assert
|
||||
// Amount is OPTIONAL in Swiss QR Bill (can be 0.00 or null for payment slips)
|
||||
|
||||
Reference in New Issue
Block a user