M3-AP-008: Testabdeckung vervollständigt
This commit is contained in:
@@ -24,7 +24,9 @@ import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@@ -258,6 +260,45 @@ class M2BatchRunProcessingUseCaseTest {
|
||||
assertTrue(lockPort.wasReleaseCalled(), "Lock should be released even when source access fails");
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixed-batch test: one document per M3 outcome type in a single run.
|
||||
* Proves that no individual outcome aborts the overall batch (AP-008 explicit contract).
|
||||
*/
|
||||
@Test
|
||||
void execute_m3MixedBatch_allOutcomeTypes_batchOverallSucceeds() throws Exception {
|
||||
MockRunLockPort lockPort = new MockRunLockPort();
|
||||
// maxPages=3 in buildConfig; pageLimitCandidate has 10 pages → exceeds limit
|
||||
StartConfiguration config = buildConfig(tempDir);
|
||||
|
||||
SourceDocumentCandidate goodCandidate = makeCandidate("good.pdf");
|
||||
SourceDocumentCandidate noTextCandidate = makeCandidate("notext.pdf");
|
||||
SourceDocumentCandidate pageLimitCandidate = makeCandidate("toobig.pdf");
|
||||
SourceDocumentCandidate technicalErrorCandidate = makeCandidate("broken.pdf");
|
||||
SourceDocumentCandidate contentErrorCandidate = makeCandidate("encrypted.pdf");
|
||||
|
||||
FixedCandidatesPort candidatesPort = new FixedCandidatesPort(List.of(
|
||||
goodCandidate, noTextCandidate, pageLimitCandidate,
|
||||
technicalErrorCandidate, contentErrorCandidate));
|
||||
|
||||
MappedExtractionPort extractionPort = new MappedExtractionPort()
|
||||
.with(goodCandidate, new PdfExtractionSuccess("Invoice text", new PdfPageCount(1)))
|
||||
.with(noTextCandidate, new PdfExtractionSuccess(" ", new PdfPageCount(1)))
|
||||
.with(pageLimitCandidate, new PdfExtractionSuccess("Some text", new PdfPageCount(10)))
|
||||
.with(technicalErrorCandidate, new PdfExtractionTechnicalError("I/O error", null))
|
||||
.with(contentErrorCandidate, new PdfExtractionContentError("PDF is encrypted"));
|
||||
|
||||
M2BatchRunProcessingUseCase useCase = new M2BatchRunProcessingUseCase(
|
||||
config, lockPort, candidatesPort, extractionPort);
|
||||
BatchRunContext context = new BatchRunContext(new RunId("m3-mixed"), Instant.now());
|
||||
|
||||
BatchRunOutcome outcome = useCase.execute(context);
|
||||
|
||||
assertTrue(outcome.isSuccess(),
|
||||
"Mixed batch with all M3 outcome types must yield batch SUCCESS");
|
||||
assertEquals(5, extractionPort.callCount(),
|
||||
"Extraction must be attempted for each of the 5 candidates");
|
||||
}
|
||||
|
||||
@Test
|
||||
void execute_m3MultipleCandidates_allProcessed_batchSucceeds() throws Exception {
|
||||
MockRunLockPort lockPort = new MockRunLockPort();
|
||||
@@ -416,4 +457,27 @@ class M2BatchRunProcessingUseCaseTest {
|
||||
throw new UnsupportedOperationException("Should not be called");
|
||||
}
|
||||
}
|
||||
|
||||
/** Per-candidate extraction port: maps each candidate to a fixed result; counts calls. */
|
||||
private static class MappedExtractionPort implements PdfTextExtractionPort {
|
||||
private final Map<SourceDocumentCandidate, PdfExtractionResult> resultMap = new LinkedHashMap<>();
|
||||
private int calls = 0;
|
||||
|
||||
MappedExtractionPort with(SourceDocumentCandidate candidate, PdfExtractionResult result) {
|
||||
resultMap.put(candidate, result);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PdfExtractionResult extractTextAndPageCount(SourceDocumentCandidate candidate) {
|
||||
calls++;
|
||||
PdfExtractionResult result = resultMap.get(candidate);
|
||||
if (result == null) {
|
||||
throw new IllegalStateException("No extraction result mapped for candidate: " + candidate);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int callCount() { return calls; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user