Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring command rollback test: inspect state after an injected failure

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A rollback test must inspect each protected table after a failure inside the transaction.

Download Spring source kit

Fail after the event insert

The local test invokes the managed command service with a test-only failure switch. The service updates the receipt, inserts an outbox row, then throws before saving its replay record. The assertion checks that the receipt still says new and both outbox and replay tables are empty. The exception alone would not prove rollback; the post-failure rows do.

The test uses a real TransactionTemplate and DataSourceTransactionManager against H2. It exercises the service proxy's method authorization too, after setting a test security context. The HTTP tests separately exercise bearer validation and filter rules. The JWT web test shows why direct service tests cannot replace filter-chain tests.

Add other failure positions later

Try duplicate event IDs, a database timeout during replay insertion and a failure after commit before the client receives its response. The last case is why replay matters. This test does not kill a process during commit or compare two independent database engines. Failure injection should be controlled in test configuration, never by a public request header.

Checked source

Java
assertThrows(IllegalStateException.class, () -> managedService.change(
    "tenant-east", "R-41", "rollback-41", command, true));
assertEquals("new", state("tenant-east"));
assertEquals(0, count("receipt_outbox"));
assertEquals(0, count("command_dedupe"));

Verification boundary

TenantReceiptCommandFlowTest.failureAfterOutboxInsertRollsBackAllThreeTables in the downloadable Spring source kit. The excerpt is shortened; the kit contains the complete test.

Costs and limits

This is a synchronous local rollback test, not a power-loss, broker or target-database crash test. It cannot show whether an external side effect already occurred, because the fixture performs none. Use a real database and process-level fault test before claiming recovery behavior.

Common Mistakes

  • Do not assert only that an exception was thrown.
  • Do not make failure injection callable by an untrusted client.
  • Do not confuse rollback before commit with recovery after commit.

Read next

Spring tenant command transaction: keep state, event and replay record together, Spring receipt outbox command: record intent without claiming delivery, Test Spring JWT authorization through filters, service proxy and SQL, Test a Spring worker at admission, lease and replay boundaries.

spring
spring-boot
command-rollback-proof
Storage details