One green restart test covers only its own failure window and resource combination.
Spring Batch restart test matrix: separate failure, process loss and changed input
Start with the checked case
The source kit now has an in-process chunk restart, a two-JVM run after FAILED was recorded and an abrupt-death recovery path with a JDBC JobRepository. It also checks one skipped row, a second row exceeding the skip budget and an exhausted temporary retry. Those are distinct behaviors. Keep their assertions on target IDs, rejected IDs and JobInstance identity, rather than relying on a log line that says COMPLETED.
Add the unproved windows
A target-database suite should kill a process after one commit, during a business write and after that write but before repository progress is durable. The H2 suite changes one source row and proves its digest guard rejects the restart. A target-database suite should test changes during the read and across replicas. Run two competing launchers to verify fencing. The source kit now covers a hard kill between chunks, STARTED-state refusal, explicit recovery and changed-input rejection on H2. A kill during a business write, the metadata race, target-database semantics and a distributed fencing test remain open.
Review outcome, not only framework state
A completed job with one skipped item still has a business exception. The report should name accepted, rejected and unprocessed IDs per manifest. The local quarantine check stores one rejected key; it does not implement a complete audited correction workflow.
Boundary sketch
// Assert after each boundary: JobInstance ID, BatchStatus,
// accepted source IDs, rejected source IDs and input version.Cost and verification
Fault injection requires process orchestration and a real repository. Keep fast unit checks separate from the slower destructive integration suite.
Common Mistakes
- Do not substitute an exception in one JVM for a process kill.
- Do not use only row counts when IDs can be duplicated or omitted.
- Do not call a skipped financial row a fully accepted import.
Read next
Spring Batch restart across two JVMs after a recorded failed execution, Spring Batch orphaned STARTED execution: inspect before relaunch, Spring Batch restart input: pin the manifest before resuming a cursor, Spring Batch SkipListener: persist a rejection key with the skipped row.
