Q17 of 40 · Karate
Compare Karate's Mock Server to WireMock — when would you choose each?
KarateMidkaratemock-serverwiremockmockingapi-testing
Short answer
Short answer: Karate Mock Server is in-process (same JVM) and stubs responses using feature files — ideal when tests and mock co-locate. WireMock runs as a standalone server, better for integration tests where the real application under test calls an external dependency. Use Karate Mock for co-located API tests; WireMock when the real app server needs a stub.
Detail
Karate Mock Server:
- Runs in the same JVM as the test
- Stubs defined in a
.featurefile usingpathMatchesandmethodIspredicates - Started programmatically:
Server mock = Karate.startMock("classpath:mocks/payment.feature").port(9999) - Best for: testing Karate scenarios that call a dependency you want to control; contract-testing style stubs
# mocks/payment.feature (stub definition)
Feature: Payment mock
Scenario: pathMatches('/payments') && methodIs('post')
* def responseStatus = 200
* def response = { transactionId: 'mock-tx-1', status: 'APPROVED' }
WireMock:
- Runs as a separate HTTP server process (or embedded via
WireMockServer) - Configured with Java fluent API or JSON stub files
- Best for: integration tests where your real application server (Spring Boot, etc.) needs to call a stubbed external API
- Works with any test library (REST Assured, Karate, plain JUnit)
Decision guide:
| Scenario | Choose |
|---|---|
| Karate tests a service that calls a third-party API | Karate Mock Server |
| REST Assured tests your service; your service calls a third-party | WireMock |
| You need request verification (was the right request sent?) | WireMock (verify() API) |
| Cross-language team, stub must work with any framework | WireMock |
// EXAMPLE
KarateMockTest.java
// Karate Mock Server — started in JUnit 5 setup
class PaymentApiMockTest {
static Server paymentMock;
@BeforeAll
static void startMock() {
paymentMock = Karate.startMock("classpath:mocks/payment-gateway.feature").port(9999);
// Set env var so karate-config.js routes to the mock
System.setProperty("payment.gateway.url", "http://localhost:9999");
}
@AfterAll
static void stopMock() { paymentMock.stop(); }
// Karate features that call the checkout service will have
// the checkout service route to localhost:9999 (the mock)
@Test
void runCheckoutTests() {
Results results = Runner.path("classpath:features/checkout").parallel(2);
assertThat(results.getFailCount()).isZero();
}
}
// mocks/payment-gateway.feature (stub)
// Scenario: pathMatches('/charge') && methodIs('post')
// * def responseStatus = 200
// * def response = { status: 'APPROVED', txId: '#(karate.uuid())' }// WHAT INTERVIEWERS LOOK FOR
Clear distinction of in-process vs standalone, the use case where each wins, and the pathMatches/methodIs predicate syntax for Karate stubs. Knowing WireMock's verify() API for asserting the outbound request was sent correctly is a senior detail.
// COMMON PITFALL
Using Karate Mock Server for integration tests where the real application runs in a separate process — the mock runs in the test JVM, not the application JVM, so the application can't reach it without network plumbing.