Keploy logo
MySQL logo

Keploy as a MySQL testing framework

Keploy mocks MySQL by recording the MySQL wire protocol beneath your driver, capturing the exact result sets your queries returned, and replaying them during tests. No MySQL instance runs in CI, no schema is created, and no seed script or H2 substitute is involved.

Generate MySQL tests free
keploy record -c "java -jar orders.jar"
18.4K+VS Code1.2M+300M+mocks created

What Keploy gives a MySQL team

Captured at the MySQL client/server protocol

Keploy reads the protocol beneath your driver, so the result sets that replay are the bytes MySQL actually sent — including the column names and types the server reported in its result metadata.

  • Below JDBC, mysql2, PyMySQL, go-sql-driver
  • Column types from the server's own metadata
  • Prepared statements and parameter binding
  • Transactions replay in order
The problem

Why MySQL 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 MySQL: by hand, with Testcontainers MySQL, or with Keploy

Testcontainers is the honest answer, and it charges for it in CI: a Docker runtime, an image pull, and a server boot per job. Keploy records that server once and replays its responses.

Select any row for the full comparison, with code.

Same coverage, three costs

What you write for MySQL 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
OrderRepositoryStub.java
hand-written
// Hand-written stub: no SQL is ever executed or validated.
package com.acme.orders;
 
import java.util.*;
 
class OrderRepositoryStub implements OrderRepository {
 
private final Map<String, Order> rows = new HashMap<>();
 
OrderRepositoryStub() {
rows.put("ord_1", new Order("ord_1", 4200, "NEW"));
}
 
@Override
public Optional<Order> findById(String id) {
return Optional.ofNullable(rows.get(id));
}
 
@Override
public void updateState(String id, String state) {
// A real UPDATE would have to satisfy constraints. This does not.
rows.computeIfPresent(id, (k, o) -> o.withState(state));
}
}

The repository interface exists only so this stub can be substituted. No query is parsed, so a syntax error or a missing index is invisible until production.

Testcontainers MySQL1–2 hours
OrderRepositoryIT.java
tool-assisted
// Testcontainers: a real MySQL 8, at the cost of Docker in CI.
package com.acme.orders;
 
import org.junit.jupiter.api.*;
import org.testcontainers.containers.MySQLContainer;
 
class OrderRepositoryIT {
 
static MySQLContainer<?> mysql =
new MySQLContainer<>("mysql:8.0")
.withInitScript("schema-and-seed.sql");
 
static OrderRepository repo;
 
@BeforeAll
static void boot() {
mysql.start();
repo = new JdbcOrderRepository(dataSource(mysql));
}
 
@AfterAll
static void stop() { mysql.stop(); }
 
@Test
void findsASeededOrder() {
var order = repo.findById("ord_1").orElseThrow();
 
assertEquals(4200, order.amountMinor());
}
}

Real SQL semantics, and every CI job that touches this class now needs a Docker daemon, an image pull, and a server boot before the first assertion.

With Keploy~5 minutes
mocks.yaml
auto-generated
# Recorded with: keploy record -c './orders-service'
# The MySQL response, captured at the protocol level.
version: api.keploy.io/v1beta1
kind: MySQL
name: mock-4
spec:
metadata:
operation: query
request:
query: "SELECT id, amount_minor, state FROM orders WHERE id = ?"
params:
- "ord_1"
response:
columns:
- name: id
type: VAR_STRING
- name: amount_minor
type: LONG
- name: state
type: VAR_STRING
rows:
- id: "ord_1"
amount_minor: 4200
state: "NEW"
affected_rows: 0
# Column types come from the server's own result metadata.

Column types and row values are what MySQL sent, not what a developer assumed. No repository interface is needed, so the production code keeps its concrete class.

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

Keploy vs the alternatives

MySQL testing tools, compared

The options a team on relational databases 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 MySQL app once, replay it forever

Keploy sits below your MySQL 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 MySQL 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

MySQL clients Keploy records, driver by driver

Keploy captures MySQL at the wire protocol, so 6 of these 8 clients need no adapter, no test double, and no MySQL instance in CI.

Quick start

Your first MySQL test suite in under five minutes

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

  1. 1Install the Keploy CLI

    One binary on the machine that will do the recording. Nothing is installed into MySQL itself.

    curl -sSL https://keploy.io/install.sh | bash
  2. 2Record with your development database reachable

    Run the app as usual. Every query it issues and every result set MySQL returns is captured together.

    keploy record -c "java -jar orders.jar"
  3. 3Exercise the paths that hit the database

    Reads, writes, transactions, and prepared statements are all recorded with their parameters and responses.

    curl localhost:8080/orders/ord_1
    curl -X POST localhost:8080/orders/ord_1/confirm -d '{"paymentToken":"tok_123"}'
  4. 4Replay with MySQL switched off

    Stop MySQL entirely and run the suite. If replay passes, the mocks are answering every query your code makes.

    keploy test -c "java -jar orders.jar" --delay 15

Ready to try it on your own MySQL service?

Ecosystem

Works with the rest of your MySQL stack

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

FAQ

MySQL 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.