test: rewrite existing Application handler tests (no mapper mock, full assertions)

ValidatePdfHandlerTests:
- Remove IMapper mock (handler no longer uses mapper)
- Add: EncryptedPdf_ReturnsIsEncryptedTrue
- Add: PdfWithAttachments_ReturnsAttachmentData
- Add: ProcessorThrowsGenericException_PropagatesException

ValidatePdfAQueryHandlerTests:
- Remove IMapper mock
- Strengthen assertions (Errors count, Warnings content)
- Add: ProcessorThrowsGenericException_PropagatesException

CheckPdfAttachmentsQueryHandlerTests:
- Remove duplicate Handle_WithBase64Pdf test (identical to WithPdfBytes)
- Add: ProcessorThrowsBadRequest_PropagatesException
- Add: ProcessorThrowsGenericException_PropagatesException
- Strengthen: assert individual attachment fields (FileName, MimeType, Size)
This commit is contained in:
2026-08-28 11:46:09 +02:00
parent 9a9d775fec
commit 9040aed1da
3 changed files with 148 additions and 230 deletions

View File

@@ -1,9 +1,7 @@
using AutoMapper;
using DocumentService.Application.Common.DTOs;
using DocumentService.Application.Common.Interfaces;
using DocumentService.Application.ValidatePdfA.Queries;
using DocumentService.Domain.Common.Exceptions;
using FluentAssertions;
using Moq;
using Xunit;
@@ -13,61 +11,32 @@ namespace DocumentService.Tests.Unit.Application.Features.ValidatePdfA;
public class ValidatePdfAQueryHandlerTests
{
private readonly Mock<IPdfProcessor> _mockPdfProcessor;
private readonly Mock<IMapper> _mockMapper;
private readonly ValidatePdfAQueryHandler _handler;
public ValidatePdfAQueryHandlerTests()
{
_mockPdfProcessor = new Mock<IPdfProcessor>();
_mockMapper = new Mock<IMapper>();
_handler = new ValidatePdfAQueryHandler(_mockPdfProcessor.Object, _mockMapper.Object);
_handler = new ValidatePdfAQueryHandler(_mockPdfProcessor.Object);
}
[Fact]
public async Task Handle_ValidPdfA_ReturnsPdfAMetadata()
public async Task Handle_ValidCompliantPdfA_ReturnsCompliantResult()
{
// Arrange
var pdfBytes = "%PDF"u8.ToArray(); // "%PDF"
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream(pdfBytes) };
var domainMetadata = new PdfAMetadata(
isValid: true,
pdfVersion: "1.7",
pageCount: 3,
fileSizeBytes: 2048,
encrypted: false,
pdfaVersion: "PDF/A-3b",
pdfaCompliant: true,
errors: [],
warnings: []
);
var expectedDto = new PdfAValidationResult
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
var expected = new PdfAValidationResult
{
IsValid = true,
PdfVersion = "1.7",
PageCount = 3,
FileSize = 2048,
Encrypted = false,
PdfAVersion = "PDF/A-3b",
PdfACompliant = true,
Errors = new List<string>(),
Warnings = new List<string>()
IsValid = true, PdfVersion = "1.7", PageCount = 3, FileSize = 2048,
Encrypted = false, PdfAVersion = "PDF/A-3b", PdfACompliant = true,
Errors = [], Warnings = []
};
_mockPdfProcessor
.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
.ReturnsAsync(domainMetadata);
_mockMapper
.Setup(x => x.Map<PdfAValidationResult>(domainMetadata))
.Returns(expectedDto);
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
// Act
var result = await _handler.Handle(query, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.IsValid.Should().BeTrue();
result.PageCount.Should().Be(3);
result.PdfVersion.Should().Be("1.7");
@@ -76,139 +45,85 @@ public class ValidatePdfAQueryHandlerTests
result.Encrypted.Should().BeFalse();
result.Errors.Should().BeEmpty();
result.Warnings.Should().BeEmpty();
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
_mockMapper.Verify(x => x.Map<PdfAValidationResult>(domainMetadata), Times.Once);
}
[Fact]
public async Task Handle_NonCompliantPdfA_ReturnsErrorsAndWarnings()
{
// Arrange
var pdfBytes = new byte[] { 0x25, 0x50, 0x44, 0x46 }; // "%PDF"
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream(pdfBytes) };
var errors = new List<string> { "Missing XMP metadata", "Invalid color space" };
var warnings = new List<string> { "Embedded font not subset" };
var domainMetadata = new PdfAMetadata(
isValid: false,
pdfVersion: "1.4",
pageCount: 2,
fileSizeBytes: 1024,
encrypted: false,
pdfaVersion: null,
pdfaCompliant: false,
errors: errors,
warnings: warnings
);
var expectedDto = new PdfAValidationResult
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
var expected = new PdfAValidationResult
{
IsValid = false,
PdfVersion = "1.4",
PageCount = 2,
FileSize = 1024,
Encrypted = false,
PdfAVersion = null,
PdfACompliant = false,
Errors = errors,
Warnings = warnings
IsValid = false, PdfVersion = "1.4", PageCount = 2, FileSize = 1024,
Encrypted = false, PdfAVersion = null, PdfACompliant = false,
Errors = ["Missing XMP metadata", "Invalid color space"],
Warnings = ["Embedded font not subset"]
};
_mockPdfProcessor
.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
.ReturnsAsync(domainMetadata);
_mockMapper
.Setup(x => x.Map<PdfAValidationResult>(domainMetadata))
.Returns(expectedDto);
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
// Act
var result = await _handler.Handle(query, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.IsValid.Should().BeFalse();
result.PdfACompliant.Should().BeFalse();
result.PdfAVersion.Should().BeNull();
result.Errors.Should().HaveCount(2);
result.Errors.Should().Contain("Missing XMP metadata");
result.Warnings.Should().HaveCount(1);
result.Errors.Should().HaveCount(2).And.Contain("Missing XMP metadata").And.Contain("Invalid color space");
result.Warnings.Should().HaveCount(1).And.Contain("Embedded font not subset");
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
}
[Fact]
public async Task Handle_EncryptedPdf_ReturnsEncryptedFlag()
public async Task Handle_EncryptedPdf_ReturnsEncryptedFlagAndErrors()
{
// Arrange
var pdfBytes = new byte[] { 0x25, 0x50, 0x44, 0x46 }; // "%PDF"
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream(pdfBytes) };
var domainMetadata = new PdfAMetadata(
isValid: true,
pdfVersion: "1.7",
pageCount: 1,
fileSizeBytes: 512,
encrypted: true,
pdfaVersion: null,
pdfaCompliant: false,
errors: new List<string> { "Encrypted PDFs cannot be PDF/A compliant" },
warnings: new List<string>()
);
var expectedDto = new PdfAValidationResult
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
var expected = new PdfAValidationResult
{
IsValid = true,
PdfVersion = "1.7",
PageCount = 1,
FileSize = 512,
Encrypted = true,
PdfAVersion = null,
PdfACompliant = false,
Errors = new List<string> { "Encrypted PDFs cannot be PDF/A compliant" },
Warnings = new List<string>()
IsValid = false, PdfVersion = "1.7", PageCount = 1, FileSize = 512,
Encrypted = true, PdfAVersion = null, PdfACompliant = false,
Errors = ["PDF/A documents cannot be encrypted"],
Warnings = []
};
_mockPdfProcessor
.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
.ReturnsAsync(domainMetadata);
_mockMapper
.Setup(x => x.Map<PdfAValidationResult>(domainMetadata))
.Returns(expectedDto);
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
// Act
var result = await _handler.Handle(query, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.Encrypted.Should().BeTrue();
result.IsValid.Should().BeFalse();
result.PdfACompliant.Should().BeFalse();
result.Errors.Should().Contain("Encrypted PDFs cannot be PDF/A compliant");
result.Errors.Should().Contain("PDF/A documents cannot be encrypted");
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
}
[Fact]
public async Task Handle_PdfProcessorThrowsException_PropagatesException()
public async Task Handle_ProcessorThrowsBadRequest_PropagatesException()
{
// Arrange
var pdfBytes = new byte[] { 0x25, 0x50, 0x44, 0x46 }; // "%PDF"
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream(pdfBytes) };
_mockPdfProcessor
.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
.ThrowsAsync(new BadRequestException("Invalid PDF format"));
// Act & Assert
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => _handler.Handle(query, CancellationToken.None)
);
var ex = await Assert.ThrowsAsync<BadRequestException>(
() => _handler.Handle(query, CancellationToken.None));
ex.Message.Should().Be("Invalid PDF format");
}
exception.Message.Should().Be("Invalid PDF format");
_mockPdfProcessor.Verify(x => x.ValidatePdfAAsync(It.IsAny<Stream>()), Times.Once);
[Fact]
public async Task Handle_ProcessorThrowsGenericException_PropagatesException()
{
// Arrange
var query = new ValidatePdfAQuery { PdfStream = new MemoryStream("%PDF"u8.ToArray()) };
_mockPdfProcessor.Setup(x => x.ValidatePdfAAsync(It.IsAny<Stream>()))
.ThrowsAsync(new Exception("Unexpected processing error"));
// Act & Assert
await Assert.ThrowsAsync<Exception>(() => _handler.Handle(query, CancellationToken.None));
}
}