test: add Application handler tests for all missing features

New test files (4 tests each — 2 success + 2 failure):
- MergePdfsCommandHandlerTests: TwoStreams, WithPageRanges, BadRequest, GenericException
- AddAnnotationHandlerTests: TextMarkup, FreeText, BadRequest (page OOB), GenericException
- AddStampHandlerTests: TextStamp, PredefinedStamp, BadRequest (opacity), GenericException
- ExtractPdfAttachmentsHandlerTests: ReturnsZip, NotFoundException, BadRequest, GenericException
- ConvertPdfAHandlerTests (ConvertTo + ConvertFrom):
  ConvertTo: ValidLevel, NotImplemented, BadRequest
  ConvertFrom: ValidPdfA, BadRequest, GenericException
This commit is contained in:
2026-08-28 11:46:18 +02:00
parent 9040aed1da
commit fbaefe1fd2
5 changed files with 555 additions and 0 deletions

View File

@@ -0,0 +1,121 @@
using DocumentService.Application.Common.Interfaces;
using DocumentService.Application.ConvertToPdfA;
using DocumentService.Application.ConvertFromPdfA;
using DocumentService.Domain.Common.Exceptions;
using FluentAssertions;
using Moq;
using Xunit;
namespace DocumentService.Tests.Unit.Application.Features.ConvertPdfA;
public class ConvertToPdfAHandlerTests
{
private readonly Mock<IPdfProcessor> _mockProcessor;
private readonly ConvertToPdfACommandHandler _handler;
private static readonly byte[] FakePdfBytes = "%PDF"u8.ToArray();
public ConvertToPdfAHandlerTests()
{
_mockProcessor = new Mock<IPdfProcessor>();
_handler = new ConvertToPdfACommandHandler(_mockProcessor.Object);
}
[Fact]
public async Task Handle_ValidPdfAndLevel_ReturnsConvertedBytes()
{
// Arrange
var command = new ConvertToPdfACommand { PdfStream = new MemoryStream(FakePdfBytes), PdfALevel = "PDF/A-3b" };
var expected = new byte[] { 0x25, 0x50, 0x44, 0x46, 0x0A };
_mockProcessor.Setup(x => x.ConvertToPdfAAsync(It.IsAny<Stream>(), "PDF/A-3b")).ReturnsAsync(expected);
// Act
var result = await _handler.Handle(command, CancellationToken.None);
// Assert
result.Should().BeEquivalentTo(expected);
_mockProcessor.Verify(x => x.ConvertToPdfAAsync(It.IsAny<Stream>(), "PDF/A-3b"), Times.Once);
}
[Fact]
public async Task Handle_ProcessorThrowsNotImplemented_PropagatesException()
{
// Arrange
var command = new ConvertToPdfACommand { PdfStream = new MemoryStream(FakePdfBytes), PdfALevel = "PDF/A-1b" };
_mockProcessor.Setup(x => x.ConvertToPdfAAsync(It.IsAny<Stream>(), "PDF/A-1b"))
.ThrowsAsync(new NotImplementedException("PDF/A conversion not yet implemented"));
// Act & Assert
var ex = await Assert.ThrowsAsync<NotImplementedException>(
() => _handler.Handle(command, CancellationToken.None));
ex.Message.Should().Contain("not yet implemented");
}
[Fact]
public async Task Handle_ProcessorThrowsBadRequest_PropagatesException()
{
// Arrange
var command = new ConvertToPdfACommand { PdfStream = new MemoryStream(FakePdfBytes), PdfALevel = "PDF/A-2b" };
_mockProcessor.Setup(x => x.ConvertToPdfAAsync(It.IsAny<Stream>(), "PDF/A-2b"))
.ThrowsAsync(new BadRequestException("PDF stream cannot be empty"));
// Act & Assert
var ex = await Assert.ThrowsAsync<BadRequestException>(
() => _handler.Handle(command, CancellationToken.None));
ex.Message.Should().Contain("empty");
}
}
public class ConvertFromPdfAHandlerTests
{
private readonly Mock<IPdfProcessor> _mockProcessor;
private readonly ConvertFromPdfACommandHandler _handler;
private static readonly byte[] FakePdfBytes = "%PDF"u8.ToArray();
public ConvertFromPdfAHandlerTests()
{
_mockProcessor = new Mock<IPdfProcessor>();
_handler = new ConvertFromPdfACommandHandler(_mockProcessor.Object);
}
[Fact]
public async Task Handle_ValidPdfA_ReturnsStandardPdfBytes()
{
// Arrange
var command = new ConvertFromPdfACommand { PdfStream = new MemoryStream(FakePdfBytes) };
var expected = new byte[] { 0x25, 0x50, 0x44, 0x46, 0x0B };
_mockProcessor.Setup(x => x.ConvertFromPdfAAsync(It.IsAny<Stream>())).ReturnsAsync(expected);
// Act
var result = await _handler.Handle(command, CancellationToken.None);
// Assert
result.Should().BeEquivalentTo(expected);
_mockProcessor.Verify(x => x.ConvertFromPdfAAsync(It.IsAny<Stream>()), Times.Once);
}
[Fact]
public async Task Handle_ProcessorThrowsBadRequest_PropagatesException()
{
// Arrange
var command = new ConvertFromPdfACommand { PdfStream = new MemoryStream(FakePdfBytes) };
_mockProcessor.Setup(x => x.ConvertFromPdfAAsync(It.IsAny<Stream>()))
.ThrowsAsync(new BadRequestException("PDF stream must be at position 0"));
// Act & Assert
var ex = await Assert.ThrowsAsync<BadRequestException>(
() => _handler.Handle(command, CancellationToken.None));
ex.Message.Should().Contain("position 0");
}
[Fact]
public async Task Handle_ProcessorThrowsGenericException_PropagatesException()
{
// Arrange
var command = new ConvertFromPdfACommand { PdfStream = new MemoryStream(FakePdfBytes) };
_mockProcessor.Setup(x => x.ConvertFromPdfAAsync(It.IsAny<Stream>()))
.ThrowsAsync(new Exception("Unexpected error"));
// Act & Assert
await Assert.ThrowsAsync<Exception>(() => _handler.Handle(command, CancellationToken.None));
}
}