Keploy logo
Spring Boot logo

Keploy as a Spring Boot testing framework

Keploy tests Spring Boot applications by recording traffic through the embedded server and every downstream call it triggers, then replaying both as assertions. There is no @SpringBootTest context to load, no @MockBean to wire, and no Testcontainers Docker requirement in CI.

Generate Spring Boot tests free
keploy record -c "./gradlew bootRun"
18.4K+VS Code1.2M+300M+mocks created

What Keploy gives a Spring Boot team

Spring Boot 2 and 3, unchanged

Keploy starts the app through bootRun, spring-boot:run, or the packaged JAR. MVC and WebFlux record identically, and the embedded server choice makes no difference because capture happens at the socket.

  • Spring Boot 2.x and 3.x
  • Tomcat, Jetty, or Undertow
  • MVC and reactive WebFlux
  • No test slice annotations needed
The problem

Why Spring Boot integration tests slow teams down

The friction is rarely the assertions. It is everything around them — spinning up dependencies, keeping mocks honest, and repairing tests after every refactor.

Three ways to do it

Testing Spring Boot: by hand, with @SpringBootTest + @MockBean, or with Keploy

Spring's testing support is excellent, but its fidelity is bounded by the mocks you declare and its speed by how many contexts your suite needs. Keploy runs the real application once instead.

Select any row for the full comparison, with code.

Same coverage, three costs

What you write for Spring Boot vs what Keploy records

All three produce the same assertion. Only the third still passes after the next refactor without anyone editing it.

By hand2–4 hours
OrderControllerTest.java
hand-written
// Hand-written: no Spring context, everything faked by hand.
package com.acme.orders;
 
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
 
class OrderControllerTest {
 
private OrderController controller;
 
@BeforeEach
void setUp() {
var repo = new FakeOrderRepository();
repo.seed(new Order("ord_1", 4200, "NEW"));
var payments = new FakePaymentClient("AUTHORIZED");
controller = new OrderController(repo, payments);
}
 
@Test
void confirmsAnAuthorizedOrder() {
var response = controller.confirm("ord_1", "tok_123");
 
assertEquals("CONFIRMED", response.getBody().state());
}
}

Fast, because Spring is never involved — which also means filters, converters, validation, and exception handlers are never exercised.

@SpringBootTest + @MockBean1–2 hours
OrderControllerIT.java
tool-assisted
// @SpringBootTest + @MockBean + Testcontainers.
package com.acme.orders;
 
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.testcontainers.containers.MySQLContainer;
import static org.mockito.Mockito.*;
 
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderControllerIT {
 
static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0");
 
@MockBean PaymentClient payments;
 
@Test
void confirmsAnAuthorizedOrder() {
// Replaces the real HTTP call, and any check that it still works.
when(payments.authorize("tok_123")).thenReturn("AUTHORIZED");
 
var response = restTemplate.postForEntity(
"/orders/ord_1/confirm", body("tok_123"), OrderView.class);
 
assertEquals(200, response.getStatusCode().value());
verify(payments).authorize("tok_123");
}
}

A full context load plus a MySQL container per run, and the payment contract is still whatever the when(...) line claims it is.

With Keploy~5 minutes
test-1.yaml
auto-generated
# Recorded with: keploy record -c './gradlew bootRun'
# No context load. No @MockBean. No container.
version: api.keploy.io/v1beta1
kind: Http
name: test-1
spec:
req:
method: POST
url: /orders/ord_1/confirm
header:
Content-Type: application/json
Authorization: Bearer <captured>
body: '{"paymentToken":"tok_123"}'
resp:
status_code: 200
body:
id: "ord_1"
state: "CONFIRMED"
amountMinor: 4200
confirmedAt: "2026-09-02T11:04:18Z"
noise:
- body.confirmedAt
- header.X-Request-Id
# Captured through the real filter chain and message converters.
mocks:
- kind: SQL
operation: "SELECT id, amount_minor, state FROM orders WHERE id = ?"
- kind: Http
url: https://api.payments.example.com/v1/payment_intents/tok_123/confirm
status: 200

This case travelled the whole Spring stack — security filters, validation, and Jackson serialisation included — because it was recorded from a real request, not a slice.

Times are estimates for authoring one endpoint’s coverage from scratch, not measurements.

Keploy vs the alternatives

Spring Boot testing tools, compared

The options a team on the JVM actually reaches for, and where each one genuinely wins. Select a row for the full comparison.

Best in classStrongPartialNot covered

Assessments reflect each tool’s documented behaviour, not benchmark measurements.

How it works

Record your Spring Boot app once, replay it forever

Keploy sits below your Spring Boot process at the network layer. It watches the calls your app already makes, then serves them back on replay so tests run with no dependencies attached.

Keploy records a GET call to /api/v1/orders/{id} on a Spring Boot service and captures the dependency calls it makes.

An example shape of a captured call. Your own endpoints and dependencies come from your real traffic, so nothing here has to be written by hand.
Mock coverage

What Keploy mocks for Spring Boot, with zero config

7 of the 8 dependencies a typical Spring Boot service talks to are stubbed from the recording itself — no mock classes, no fixture files, no containers in CI.

Quick start

Your first Spring Boot test suite in under five minutes

Every command below runs against your existing Spring Boot service. Nothing in your source tree changes.

  1. 1Install the Keploy CLI

    One binary. Nothing is added to your Maven or Gradle build, and no agent is attached to the JVM.

    curl -sSL https://keploy.io/install.sh | bash
  2. 2Record through your normal start command

    Use bootRun, spring-boot:run, or the built JAR — whichever your team already runs locally.

    keploy record -c "./gradlew bootRun"
  3. 3Exercise the endpoints that matter

    Every request served while recording becomes a test case, complete with the SQL and upstream HTTP it triggered.

    curl -X POST localhost:8080/orders/ord_1/confirm -H 'Content-Type: application/json' -d '{"paymentToken":"tok_123"}'
  4. 4Replay in CI as a single step

    Replay boots the app once against recorded mocks — no MySQL service, no Docker daemon, no context reloads.

    keploy test -c "java -jar build/libs/orders.jar" --delay 20

Ready to try it on your own Spring Boot service?

Ecosystem

Works with the rest of your Spring Boot stack

Keploy records at the network layer, so framework and driver choices inside your Spring Boot app do not change how it captures traffic.

  • Java logo

    Java

    The language page covers JVM-wide capture and mock coverage.

  • Spring Data JPA logo

    Spring Data JPA

    Repository methods record as the SQL Hibernate emits.

  • Spring WebFlux logo

    Spring WebFlux

    Reactive endpoints record identically — capture is not blocking-aware.

  • Spring Security logo

    Spring Security

    Filters run on every recorded request, so auth is genuinely exercised.

  • Gradle logo

    Gradle

    Wrap bootRun; no plugin or test task changes needed.

  • Apache Maven logo

    Apache Maven

    Same for spring-boot:run or the packaged JAR.

FAQ

Spring Boot testing with Keploy: common questions

Join our GlobalCommunity

Connect with developers worldwide. Follow updates, ask questions, share feedback, and ship faster with other Keploy builders.

1.2M+Installs
18.4K+GitHub
100K+Devs
300M+Mocks
1K+Contributors
#1OSS Trending
4.9★★★★★from 500+ reviews onG2GartnerVS CodeChrome
★★★★★

Best report of integration and API tests I've seen — which we don't get from RestAssured.

G2
★★★★★

Future of microservices testing. I don't write tests now!

G2 · 5/5
★★★★★

An amazing product that simplifies the automation.

Gartner · 4.0
XGitHubSlackYouTubeLinkedIn
Built by developers, for developers.Let's build the future, together.