Add FileUpload test fixture and port RotationControllerTest (controller-test pattern)

This commit is contained in:
Anthony Stirling
2026-06-14 22:53:22 +01:00
parent e0b898c1a1
commit e55dad4851
2 changed files with 62 additions and 23 deletions
@@ -1,6 +1,7 @@
package stirling.software.SPDF.controller.api;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
@@ -14,19 +15,19 @@ import java.nio.file.Files;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.jboss.resteasy.reactive.multipart.FileUpload;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.web.MockMultipartFile;
import jakarta.ws.rs.core.Response;
import stirling.software.SPDF.model.api.general.RotatePDFRequest;
import stirling.software.common.service.CustomPDFDocumentFactory;
import stirling.software.common.testsupport.TestFileUploads;
import stirling.software.common.util.TempFile;
import stirling.software.common.util.TempFileManager;
@@ -56,48 +57,37 @@ public class RotationControllerTest {
@Test
public void testRotatePDF() throws IOException {
// Create a mock file
MockMultipartFile mockFile =
new MockMultipartFile(
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, new byte[] {1, 2, 3});
RotatePDFRequest request = new RotatePDFRequest();
request.setFileInput(mockFile);
request.setAngle(90);
// The controller binds @RestForm FileUpload and rebuilds the RotatePDFRequest internally.
FileUpload fileUpload = TestFileUploads.pdf(new byte[] {1, 2, 3});
PDDocument mockDocument = mock(PDDocument.class);
PDPageTree mockPages = mock(PDPageTree.class);
PDPage mockPage = mock(PDPage.class);
when(pdfDocumentFactory.load(request)).thenReturn(mockDocument);
when(pdfDocumentFactory.load(any(RotatePDFRequest.class))).thenReturn(mockDocument);
when(mockDocument.getPages()).thenReturn(mockPages);
when(mockPages.iterator())
.thenReturn(java.util.Collections.singletonList(mockPage).iterator());
when(mockPage.getRotation()).thenReturn(0);
// Act
ResponseEntity<Resource> response = rotationController.rotatePDF(request);
Response response = rotationController.rotatePDF(fileUpload, null, 90);
// Assert
verify(mockPage).setRotation(90);
assertNotNull(response);
assertEquals(200, response.getStatusCode().value());
assertEquals(200, response.getStatus());
}
@Test
public void testRotatePDFInvalidAngle() {
// Create a mock file
MockMultipartFile mockFile =
new MockMultipartFile(
"file", "test.pdf", MediaType.APPLICATION_PDF_VALUE, new byte[] {1, 2, 3});
RotatePDFRequest request = new RotatePDFRequest();
request.setFileInput(mockFile);
request.setAngle(45); // Invalid angle
FileUpload fileUpload = TestFileUploads.pdf(new byte[] {1, 2, 3});
// Act & Assert: Controller direkt aufrufen und Exception erwarten
// Act & Assert: call the controller directly and expect the validation exception.
IllegalArgumentException exception =
assertThrows(
IllegalArgumentException.class,
() -> rotationController.rotatePDF(request));
() -> rotationController.rotatePDF(fileUpload, null, 45));
assertEquals("Angle must be a multiple of 90", exception.getMessage());
}
}
@@ -0,0 +1,49 @@
package stirling.software.common.testsupport;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.jboss.resteasy.reactive.multipart.FileUpload;
/**
* Builds RESTEasy Reactive {@link FileUpload} stubs for unit tests. The migrated controllers bind
* {@code @RestForm FileUpload} and wrap it via {@code FileUploadMultipartFile.of(...)}, which reads
* {@code uploadedFile()}/{@code fileName()}/{@code size()}. This backs the mock with a real temp
* file so those reads work whether or not the collaborator (e.g. {@code CustomPDFDocumentFactory})
* is itself mocked. All stubs are lenient so a test that never reaches a given accessor does not
* trip strict-stubbing.
*/
public final class TestFileUploads {
private TestFileUploads() {}
public static FileUpload of(byte[] content, String fileName, String contentType) {
try {
byte[] bytes = content == null ? new byte[0] : content;
String suffix = fileName == null ? "file" : fileName.replaceAll("[^a-zA-Z0-9._-]", "_");
Path tmp = Files.createTempFile("test-upload-", "-" + suffix);
tmp.toFile().deleteOnExit();
Files.write(tmp, bytes);
FileUpload upload = mock(FileUpload.class);
lenient().when(upload.uploadedFile()).thenReturn(tmp);
lenient().when(upload.filePath()).thenReturn(tmp);
lenient().when(upload.fileName()).thenReturn(fileName);
lenient().when(upload.contentType()).thenReturn(contentType);
lenient().when(upload.size()).thenReturn((long) bytes.length);
return upload;
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
/** Convenience for a PDF part named {@code test.pdf}. */
public static FileUpload pdf(byte[] content) {
return of(content, "test.pdf", "application/pdf");
}
}