refactor(importing): inject FileStreamOpener to remove test-only seam
DocumentImporter exposed a package-private openFileStream(File) so a Mockito spy could force the IO-error branch of isPdfMagicBytes. The test-only seam leaked into production: the method existed for testing, not for any production extensibility. Replace with a constructor-injected FileStreamOpener interface (single abstract method, @FunctionalInterface) and a one-line @Component DefaultFileStreamOpener delegate. Tests now inject a mock opener instead of spying on the importer itself, which is also a more idiomatic Mockito usage. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -49,12 +49,18 @@ class DocumentImporterTest {
|
||||
@Mock TagService tagService;
|
||||
@Mock S3Client s3Client;
|
||||
@Mock ThumbnailAsyncRunner thumbnailAsyncRunner;
|
||||
@Mock FileStreamOpener fileStreamOpener;
|
||||
|
||||
DocumentImporter importer;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
importer = new DocumentImporter(documentService, personService, tagService, s3Client, thumbnailAsyncRunner);
|
||||
void setUp() throws java.io.IOException {
|
||||
// Default opener delegates to FileInputStream — tests that need to force an IOException
|
||||
// override this stub locally (load_skipsFile_whenMagicByteCheckThrowsIoException).
|
||||
lenient().when(fileStreamOpener.open(any(File.class)))
|
||||
.thenAnswer(inv -> new java.io.FileInputStream(inv.getArgument(0, File.class)));
|
||||
importer = new DocumentImporter(documentService, personService, tagService, s3Client,
|
||||
thumbnailAsyncRunner, fileStreamOpener);
|
||||
ReflectionTestUtils.setField(importer, "bucketName", "test-bucket");
|
||||
}
|
||||
|
||||
@@ -305,11 +311,11 @@ class DocumentImporterTest {
|
||||
lenient().when(documentService.findByOriginalFilename(any())).thenReturn(Optional.empty());
|
||||
Path xlsx = writeDocs(tempDir, docRow("W-0001", "", "", "", "", "", "", "", ""));
|
||||
|
||||
DocumentImporter spyImporter = org.mockito.Mockito.spy(importer);
|
||||
org.mockito.Mockito.doThrow(new java.io.IOException("read error"))
|
||||
.when(spyImporter).openFileStream(any(File.class));
|
||||
// FileStreamOpener is injected — stub it to throw, no spy on the importer needed.
|
||||
org.mockito.Mockito.when(fileStreamOpener.open(any(File.class)))
|
||||
.thenThrow(new java.io.IOException("read error"));
|
||||
|
||||
DocumentImporter.LoadResult result = spyImporter.load(xlsx.toFile());
|
||||
DocumentImporter.LoadResult result = importer.load(xlsx.toFile());
|
||||
|
||||
assertThat(result.skippedFiles())
|
||||
.extracting(ImportStatus.SkippedFile::reason)
|
||||
|
||||
Reference in New Issue
Block a user