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

Spring tests: separate business rules, wiring and transport

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A test boundary selects which components are real and which are supplied fixtures, determining the failures that test can detect.

Download Spring source kit

This lesson uses the downloadable source kit: Java 21, Spring Boot 4.0.8 and its managed Spring Framework 7 dependencies. The version is pinned for repeatable builds.

Three tests answer three questions

The direct report test asks whether a supplied exporter produces the expected report. The context test asks whether the container can create and reuse the report bean. The MVC test asks whether a JSON request is converted, validated and translated into the promised response.

Starting the whole Boot application for every test adds unrelated failure modes to a small assertion. Testing everything through direct method calls misses wiring, request filters and serialization. Use both where each supplies distinct evidence.

Name the excluded behavior

H2 rollback tests establish local transaction behavior for the fixture schema. They do not check a production database’s lock timing, migrations or multi-instance recovery. A deterministic cache test does not establish distributed invalidation.

The source kit makes those limits visible. A failing test should identify a contract the service actually promises; avoid tests that simply assert every private field has the value used to initialize it.

Checked source

Java
assertEquals("csv:receipt", new ContainerContracts.ReceiptReport(new ContainerContracts.CsvExporter()).render());
// Container identity, MVC conversion and real HTTP filters have separate tests.
assertThrows(DataIntegrityViolationException.class, ledger::batchThatFails);
assertEquals(0, ledger.count());

Test the boundary

Run mvn test in the source-kit directory. CoreBoundaryTest and ReceiptBoundaryTest checks the behavior described here. Java excerpts belong to the named source-kit classes; they are not independent source files unless the complete class is shown.

Costs and boundaries

Test cost grows with the boundary’s assembly and external resources. Keep focused tests fast enough to run repeatedly, and retain integration tests for contracts that focused fixtures cannot establish.

Common Mistakes

  • Do not treat H2 as proof of production database isolation.
  • Do not start a server to test an ordinary pure method.
  • Do not omit filters from a test described as security coverage.

Read next

Context testing, Spring MockMvc tests: HTTP behavior without claiming a real network test, Java test boundaries: injected collaborators and behavior-focused checks.

Continue with checked Spring boundaries

Continue with Spring test failures: prove the layer that can reject the request.

Continue with checked worker recovery

Continue with Test a Spring worker at admission, lease and replay boundaries.

Continue with checked tenant security

Continue with Test Spring JWT authorization through filters, service proxy and SQL.

Continue with checked upload and readiness

Continue with Spring MockMvc multipart tests: what the fixture proves.

Continue with checked relay behavior

Continue with Spring relay failure trace: inspect persisted state at each cut point.

Continue with checked settings and schema rollout

Continue with Spring schema rollout tests: check old and new writers at every phase.

Continue with checked Boot startup

Continue with Spring Boot migration tests: distinguish a test starter from a runtime rollout.

Release boundary continuation

Continue with Spring release tests: distinguish context checks from process and platform checks.

Checked outbound HTTP continuation

Continue with Test Spring RestClient on a socket without claiming a remote service.

Checked process continuation

Continue with Spring Boot config tests: what a child JVM proves and what deployment still owes.

Checked config-data continuation

Continue with Spring Boot file-tree tests: prove binding without claiming secret delivery.

Kafka continuation

Continue with Spring Kafka testing layers: know what a direct listener test cannot prove.

GraphQL continuation

Continue with Spring GraphQL service tests: stop short of claiming an HTTP endpoint.

Reactive database continuation

Continue with Spring R2DBC fixture isolation: keep incompatible H2 versions out of one test classpath.

Related boundary

Continue with Spring AI evaluations: separate model quality from enforced safety contracts.

Related Spring path

Continue with Spring Modulith module tests: distinguish structure verification from a sliced context.

Related Spring path

Continue with Spring Batch crash recovery: test the repository and input across two processes.

spring
spring-boot
testing-boundaries
Storage details