Skip to main content

EXTENSIONS

Test Doubles and Mocking

Create standalone mock servers with stateful behavior for API testing, consumer-driven contracts, and microservice development without external dependencies.

Karate v2 — Mock Server Rewrite

Karate v2 features a completely rewritten mock server with the new JS engine and a Netty-based HTTP server for improved performance. All v1 mock APIs are preserved. New: JavaScript file handlers, built-in CORS support, and non-blocking response delays.

On this page:

Request Matching

Matching Predicates

Karate provides helper functions for request matching:

FunctionDescriptionExample
pathMatches()Match request paths with path parameterspathMatches('/users/{id}')
methodIs()Check HTTP method (recommended)methodIs('post')
paramExists()Check if query parameter existsparamExists('name')
paramValue()Get single query parameter valueparamValue('limit')
typeContains()Match Content-Type headertypeContains('xml')
acceptContains()Match Accept headeracceptContains('json')
headerContains()Check header contentsheaderContains('Authorization', 'Bearer')
bodyPath()Query request body using JsonPath/XPathbodyPath('$.username')

Request Variables

Available variables for inspecting incoming requests:

VariableDescriptionExample Value
requestRequest body (parsed as JSON/XML, or string){ "name": "John" }
requestBytesRaw request body as bytes (for binary content)[byte array]
requestMethodHTTP method in uppercaseGET, POST
requestPathPath without query string/users/1
requestUriPath with query string/users?page=2
requestUrlBaseProtocol, host, and porthttp://localhost:8080
requestHeadersAll headers (Map of Lists){ 'Content-Type': ['application/json'] }
requestParamsQuery parameters (Map of Lists){ 'page': ['2'] }
requestPartsMultipart parts for file uploads{ 'file': [{ filename: '...' }] }
pathParamsPath parameters from URL pattern{ 'id': '1' }
Best Practice

Use helper functions like methodIs('post') and paramValue('page') instead of accessing raw variables directly.

Basic Mock Server

Simple HTTP Mock

Create a basic mock server that responds to requests:

Gherkin
Feature: Simple user mock

Background:
* def users = { '1': { id: 1, name: 'John Doe' } }

Scenario: pathMatches('/users/{id}') && methodIs('get')
* def user = users[pathParams.id]
* def response = user || { error: 'Not found' }
* def responseStatus = user ? 200 : 404

This mock returns predefined user data or a 404 error.

Starting the Mock Server

Start the mock server within a test:

Gherkin
Feature: Test with user service mock

Background:
* def mock = karate.start('user-service-mock.feature')
* url 'http://localhost:' + mock.port

Scenario: Get user by ID
Given path 'users', '1'
When method get
Then status 200
And match response == { id: 1, name: 'John Doe' }

Multiple Endpoints

Add GET and POST endpoints to your mock:

Gherkin
Feature: User service with multiple endpoints

Background:
* def users = { '1': { id: 1, name: 'John Doe', email: 'john@example.com' } }

Scenario: pathMatches('/users/{id}') && methodIs('get')
* def user = users[pathParams.id]
* def response = user || { error: 'User not found' }
* def responseStatus = user ? 200 : 404

Scenario: pathMatches('/users') && methodIs('post')
* def newUser = request
* def newId = (karate.sizeOf(users) + 1) + ''
* def responseStatus = 400
* if (newUser.name && newUser.email) users[newId] = karate.merge(newUser, { id: ~~newId })
* if (newUser.name && newUser.email) response = users[newId]
* if (newUser.name && newUser.email) responseStatus = 201
* if (responseStatus == 400) response = { error: 'Missing required fields' }

Stateful Mocks

Product Catalog Mock

Create a mock with shared state across requests:

Gherkin
Feature: Product catalog mock

Background:
* def products = { '1': { id: 1, name: 'Laptop', price: 999 }, '2': { id: 2, name: 'Mouse', price: 29 } }

Scenario: pathMatches('/products') && methodIs('get')
* def response = karate.valuesOf(products)

Scenario: pathMatches('/products/{id}') && methodIs('get')
* def product = products[pathParams.id]
* def response = product || { error: 'Product not found' }
* def responseStatus = product ? 200 : 404

CRUD Mock

Implement create, read, update, delete operations with shared state:

Gherkin
Feature: CRUD mock

Background:
* def nextId = 1
* def items = {}

Scenario: pathMatches('/items') && methodIs('post')
* def item = request
* item.id = nextId
* items[nextId + ''] = item
* nextId = nextId + 1
* def response = item
* def responseStatus = 201

Scenario: pathMatches('/items/{id}') && methodIs('get')
* def item = items[pathParams.id]
* def response = item || { error: 'Not found' }
* def responseStatus = item ? 200 : 404

Scenario: pathMatches('/items/{id}') && methodIs('delete')
* def item = items[pathParams.id]
* if (item) delete items[pathParams.id]
* def responseStatus = item ? 204 : 404

Catch-All Scenario

Always include a catch-all scenario as the last one to handle unmatched requests. An empty scenario description evaluates to true:

Gherkin
Feature: Mock with catch-all

Background:
* def users = { '1': { id: 1, name: 'John' } }

Scenario: pathMatches('/users/{id}') && methodIs('get')
* def response = users[pathParams.id] || { error: 'Not found' }
* def responseStatus = users[pathParams.id] ? 200 : 404

Scenario:
# Catch-all: returns 404 for any unmatched request
* def response = { error: 'Endpoint not found' }
* def responseStatus = 404

Response Configuration

Status Codes and Headers

Control mock responses using built-in variables:

VariableDescriptionDefault
responseResponse body (JSON, XML, string, or bytes)''
responseStatusHTTP status code200
responseHeadersResponse headers as JSON object{}
responseDelayDelay in milliseconds before responding0
Gherkin
Feature: Response configuration

Scenario: pathMatches('/api/data')
* def response = { message: 'Created successfully' }
* def responseStatus = 201
* def responseHeaders = { 'X-Request-Id': 'abc123', 'Cache-Control': 'no-cache' }

Simulating Latency

Add realistic network delays to test timeout handling and loading states. In Karate v2, delays use Netty's non-blocking scheduler — they don't consume threads:

Gherkin
Feature: Delayed responses

Scenario: pathMatches('/slow-api')
* def responseDelay = 2000
* def response = { data: 'delayed response' }

For random delays across all scenarios, use configure afterScenario:

Gherkin
Feature: Random delay mock

Background:
* configure afterScenario = function(){ karate.set('responseDelay', 100 + Math.random() * 500) }

Scenario: pathMatches('/api/data')
* def response = { message: 'Response with random 100-600ms delay' }

Per-Request Setup with beforeScenario

Mock Background only runs once at server init, so use configure beforeScenario for logic that must run per incoming request (e.g. request-scoped counters, request logging, dynamic auth checks):

Gherkin
Feature: Per-request counter

Background:
* def hits = { count: 0 }
* configure beforeScenario = function(){ hits.count++ }

Scenario: pathMatches('/status')
* def response = { hits: hits.count }

Both beforeScenario and afterScenario surface hook failures as an HTTP 500 response with the error in the body — wrap the hook body in try/catch if you want to suppress errors. See Hooks and Lifecycle for broader lifecycle coverage.

Starting Mock Servers

Within a Karate Test

Use karate.start() to launch a mock server from within a feature file. The mock starts on a random available port:

Gherkin
Feature: Test with embedded mock

Background:
* def mock = karate.start('classpath:mocks/user-mock.feature')
* url 'http://localhost:' + mock.port

Scenario: Call mock endpoint
Given path 'users', 1
When method get
Then status 200
And match response.name == '#string'

For more control, pass a JSON configuration:

Gherkin
Feature: Mock with options

Background:
* def mock = karate.start({ mock: 'user-mock.feature', port: 8090 })
* url 'http://localhost:8090'
OptionDescription
mockPath to mock feature file (required)
portFixed port number (default: random)
sslEnable HTTPS (default: false)
certSSL certificate path
keySSL private key path

Java API

Embed mocks in JUnit tests using MockServer:

Karate v2
import io.karatelabs.core.MockServer;

public class MyTest {
static MockServer mockServer;

@BeforeAll
static void setup() {
mockServer = MockServer
.feature("classpath:mocks/user-mock.feature")
.http(0) // Random port
.build();
}

@AfterAll
static void cleanup() {
mockServer.stop();
}

@Test
void testWithMock() {
int port = mockServer.getPort();
// Use port in your tests
}
}
Karate v1 API (still works via compatibility shim)
Karate v1
import com.intuit.karate.core.MockServer;

// Same API — delegates to v2 internally
MockServer server = MockServer
.feature("classpath:mock.feature")
.arg("key", "value")
.http(0).build();

CLI Mock Server

Start a mock server from the command line:

Terminal
karate mock -m api.feature -p 8080
karate mock -m users.feature -m orders.feature -p 8080 # multiple features
karate mock -m api.feature -p 8443 --ssl # HTTPS

Proxy Mode

Use karate.proceed() to forward requests to real backend services. This enables "AOP for web services" - you can intercept, modify, or conditionally stub requests.

Forwarding Requests

Forward all matching requests to a backend service:

Gherkin
Feature: API proxy

Scenario: pathMatches('/api/users')
* karate.proceed('https://jsonplaceholder.typicode.com')

After karate.proceed() returns, response and responseHeaders contain the backend's response. You can modify them before returning to the client.

Modifying Proxied Responses

Intercept and enrich responses from the backend:

Gherkin
Feature: Response enrichment proxy

Scenario: pathMatches('/api/users/{id}')
* karate.proceed('https://jsonplaceholder.typicode.com')
# Add metadata to response
* response.cached = false
* response.timestamp = new Date().toISOString()

Conditional Stubbing

Stub some requests while forwarding others:

Gherkin
Feature: Selective proxy

Background:
* def backendUrl = 'https://jsonplaceholder.typicode.com'

Scenario: pathMatches('/api/users/99999')
# Stub non-existent user for testing
* def response = { id: 99999, name: 'Test User' }

Scenario: pathMatches('/api/users/{id}')
# Forward all other user requests to real backend
* karate.proceed(backendUrl)

Server Lifecycle

Understanding the mock server lifecycle is essential for building effective mocks.

Background vs Scenario

Unlike normal Karate tests, mock servers have a different execution model:

PhaseNormal KarateMock Server
BackgroundRuns before each ScenarioRuns once on startup
ScenarioRuns sequentiallyEvaluated per incoming request

Request Matching

For each incoming HTTP request:

  1. Scenario expressions are evaluated in order from top to bottom
  2. The first scenario whose expression evaluates to true is executed
  3. If no scenario matches, no response is returned (connection timeout)
Scenario Order Matters

Place more specific scenarios before general ones. For example, put pathMatches('/users/admin') before pathMatches('/users/{id}').

Using karate.abort()

Stop scenario execution without returning a response:

Gherkin
Feature: Protected endpoint

Scenario: pathMatches('/protected')
* def auth = karate.request.header('authorization')
* if (!auth) karate.abort()
* def response = { message: 'Authorized access' }

Aborted scenarios result in connection timeout for the client - useful for simulating authentication failures.

CORS and Headers

Enable CORS

For browser-based testing, enable CORS with a single line. This automatically adds Access-Control-Allow-Origin: * and related headers:

Gherkin
Feature: Browser-friendly mock

Background:
* configure cors = true

Scenario: pathMatches('/api/data')
* def response = { message: 'CORS enabled' }

Global Response Headers

Set headers that apply to all responses:

Gherkin
Feature: Mock with global headers

Background:
* configure responseHeaders = { 'Content-Type': 'application/json', 'X-Powered-By': 'Karate' }

Scenario: pathMatches('/api/data')
* def response = { message: 'Has global headers' }

Scenario-level responseHeaders override global settings for individual endpoints.

Error Simulation

Test error handling by returning various HTTP error codes:

Gherkin
Feature: Error simulation

Scenario: pathMatches('/api/error/400')
* def response = { error: 'Bad Request', message: 'Invalid input' }
* def responseStatus = 400

Scenario: pathMatches('/api/error/500')
* def response = { error: 'Internal Server Error' }
* def responseStatus = 500

Scenario: pathMatches('/api/timeout')
* def responseDelay = 30000
* def response = { message: 'This will timeout most clients' }

File Uploads

Handle multipart file uploads using requestParts:

Gherkin
Feature: File upload mock

Scenario: pathMatches('/upload') && methodIs('post')
* def filePart = requestParts['file'][0]
* def response =
"""
{
filename: '#(filePart.filename)',
contentType: '#(filePart.contentType)',
size: '#(filePart.value.length)'
}
"""
* def responseStatus = 201

Each part in requestParts contains: name, filename, contentType, charset, transferEncoding, and value (raw bytes).

Standalone Mock Server

Run mocks as standalone servers using the karate CLI via the mock subcommand:

# Basic server
karate mock -m mock.feature -p 8080

# Multiple mock files (evaluated in order)
karate mock -m users.feature -m orders.feature -p 8080

# With SSL (auto-generated certificate)
karate mock -m mock.feature -p 8443 -s

# Hot reload during development
karate mock -m mock.feature -p 8080 -W

# With environment
karate mock -m mock.feature -p 8080 -e staging

Command-Line Options

OptionDescription
-mMock feature file (can specify multiple)
-pPort number
-sEnable SSL (auto-generates certificate if none provided)
-cSSL certificate file (PEM format)
-kSSL private key file (PEM format)
-eSet karate.env value
-WWatch mode - hot reload on file changes
--keep-original-headersPreserve header case (for HTTP/1 compatibility)

Stopping a Running Server

Send a GET request to the admin endpoint to gracefully stop the server:

# Stop HTTP server
curl http://localhost:8080/__admin/stop

# Stop HTTPS server (ignore certificate)
curl -k https://localhost:8443/__admin/stop

Or call mockServer.stop() if using the Java API.

Pure JSON State

Mock state must use pure JSON objects. Avoid storing Java objects or JavaScript functions with closures - they may cause issues.

The World's Smallest Microservice

This complete CRUD microservice fits in under 300 characters - demonstrating the power of Karate mocks:

Gherkin
Feature:

Background:
* def id = 0
* def m = {}

Scenario: methodIs('post')
* def c = request
* def id = ~~(id + 1)
* c.id = id
* m[id + ''] = c
* def response = c

Scenario: pathMatches('/cats/{id}')
* def response = m[pathParams.id]

Scenario:
* def response = $m.*

This implements POST (create), GET by ID, and GET all for a /cats resource. The ~~ operator converts to integer, and $m.* returns all values from the map.

Matcher Functions Reference

Each matcher function is designed to be used in Scenario expressions. You can combine multiple matchers with && and || operators for precise request matching.

pathMatches(pattern)

Match URL paths using placeholders. Extracted values are available in the pathParams map:

Gherkin
Scenario: pathMatches('/users/{id}')
# /users/42 -> pathParams.id == '42'
* def response = { id: pathParams.id }

Scenario: pathMatches('/v1/cats/{catId}/toys/{toyId}')
# /v1/cats/3/toys/7 -> pathParams.catId == '3', pathParams.toyId == '7'
* def response = { cat: pathParams.catId, toy: pathParams.toyId }

Path parameters are always strings. Use ~~pathParams.id to convert to an integer.

methodIs(method)

Case-insensitive HTTP method check. Always preferred over comparing requestMethod directly:

Gherkin
Scenario: pathMatches('/users') && methodIs('get')
* def response = []

Scenario: pathMatches('/users') && methodIs('post')
* def response = request
* def responseStatus = 201

typeContains(str)

Check if the Content-Type header contains the given substring:

Gherkin
Scenario: pathMatches('/data') && typeContains('xml')
# Matches application/xml, text/xml, application/soap+xml, etc.
* def response = '<result>OK</result>'
* def responseHeaders = { 'Content-Type': 'application/xml' }

Scenario: pathMatches('/data') && typeContains('json')
# Matches application/json, application/ld+json, etc.
* def response = { result: 'OK' }

acceptContains(str)

Check if the Accept header contains the given substring. Useful for content negotiation:

Gherkin
Scenario: pathMatches('/data') && acceptContains('xml')
* def responseHeaders = { 'Content-Type': 'application/xml' }
* def response = '<data>value</data>'

Scenario: pathMatches('/data') && acceptContains('json')
* def response = { data: 'value' }

headerContains(name, value)

Check if any value of a named header contains the given substring:

Gherkin
Scenario: pathMatches('/protected') && headerContains('Authorization', 'Bearer')
* def response = { status: 'authorized' }

Scenario: pathMatches('/protected')
* def responseStatus = 401
* def response = { error: 'Missing or invalid authorization' }

paramValue(name)

Get the value of a query string or form parameter. Returns null if the parameter does not exist:

Gherkin
Scenario: pathMatches('/search') && paramValue('q')
* def query = paramValue('q')
* def limit = paramValue('limit') || '10'
* def response = { query: query, limit: ~~limit, results: [] }

paramExists(name)

Check whether a query string or form parameter exists, regardless of its value:

Gherkin
Scenario: pathMatches('/items') && paramExists('verbose')
* def response = { items: [], debug: true, timestamp: new Date().toISOString() }

Scenario: pathMatches('/items')
* def response = { items: [] }

bodyPath(expression)

Extract a value from the request body using JsonPath or XPath. Paths starting with / are treated as XPath, otherwise JsonPath:

Gherkin
Scenario: pathMatches('/process') && bodyPath('$.action') == 'submit'
* def name = bodyPath('$.user.name')
* def response = { accepted: true, name: name }

Scenario: pathMatches('/soap') && bodyPath('/Envelope/Body/Action') == 'GetUser'
* def response = '<User><Name>John</Name></User>'

Request and Response Variables

Request Variables

The following variables are automatically set for each incoming request and are available in all mock Scenario blocks:

VariableTypeDescription
requestObjectParsed request body — JSON becomes a JS object, XML becomes an XML object, otherwise a string
requestBytesbyte[]Raw request body as a byte array, useful for binary content
requestPathStringURL path without the query string, e.g. /users/1
requestUriStringFull path including the query string, e.g. /users?page=2
requestUrlBaseStringProtocol, host, and port, e.g. http://localhost:8080
requestMethodStringHTTP method in uppercase, e.g. GET, POST
requestHeadersMapAll headers as a map where each value is a list of strings
requestCookiesMapRequest cookies as a map of { name, value } objects
requestParamsMapQuery string or form parameters as a map of string lists
requestPartsMapMultipart parts for file uploads, keyed by part name
pathParamsMapPath parameters extracted by pathMatches(), e.g. { id: '42' }

Response Variables

Set these variables within a Scenario to control what the mock server returns:

VariableTypeDefaultDescription
responseanynullResponse body — auto-serialized to JSON, XML, or plain text
responseStatusint200HTTP status code
responseHeadersMap{}Additional response headers, merged with global headers
responseDelayint0Delay in milliseconds before sending the response (non-blocking in v2)
Global vs Scenario Headers

Use configure responseHeaders in the Background to set headers for all responses. Setting responseHeaders in a Scenario overrides the global values for that specific response.

Stateful Mocks

Variables defined in the Background section execute once on server startup and persist across all requests. This makes it straightforward to build mocks that maintain state, such as an in-memory datastore.

In-Memory CRUD Example

The following mock implements a complete REST resource with create, read, update, and delete operations backed by a simple JavaScript map:

Gherkin
Feature: Task manager mock

Background:
* def nextId = 1
* def tasks = {}
* configure responseHeaders = { 'Content-Type': 'application/json' }

Scenario: pathMatches('/tasks') && methodIs('get')
* def response = karate.valuesOf(tasks)

Scenario: pathMatches('/tasks') && methodIs('post')
* def task = request
* task.id = nextId
* task.status = task.status || 'pending'
* tasks[nextId + ''] = task
* nextId = nextId + 1
* def response = task
* def responseStatus = 201

Scenario: pathMatches('/tasks/{id}') && methodIs('get')
* def task = tasks[pathParams.id]
* def response = task || { error: 'Task not found' }
* def responseStatus = task ? 200 : 404

Scenario: pathMatches('/tasks/{id}') && methodIs('put')
* def existing = tasks[pathParams.id]
* if (!existing) responseStatus = 404
* if (!existing) response = { error: 'Task not found' }
* if (existing) tasks[pathParams.id] = karate.merge(existing, request)
* if (existing) response = tasks[pathParams.id]

Scenario: pathMatches('/tasks/{id}') && methodIs('delete')
* def existing = tasks[pathParams.id]
* if (existing) delete tasks[pathParams.id]
* def responseStatus = existing ? 204 : 404

Scenario:
* def responseStatus = 404
* def response = { error: 'Not found' }

Because the Background runs only once, nextId and tasks retain their values across every request. Creating a task increments the ID counter permanently, and subsequent GET requests see all previously created tasks.

Thread Safety

The mock handler synchronizes request processing, so concurrent access to shared state is safe. However, you should keep state as pure JSON objects. Avoid storing Java objects or JavaScript closures in mock state.

Proxy Mode

Karate mocks can act as HTTP proxies using karate.proceed(). This enables a powerful pattern sometimes called "AOP for web services" — you can intercept, inspect, modify, or selectively stub requests while forwarding the rest to a real backend.

Forward to a Specific Target

Pass a URL to karate.proceed() to forward the request to that host. The request path, method, headers, and body are all forwarded:

Gherkin
Scenario: pathMatches('/api/{path}')
* karate.proceed('https://api.example.com')
# response, responseStatus, and responseHeaders are now set from the backend

Forward to the Original Host

Call karate.proceed() with no arguments to forward using the host from the original request. This is useful when the mock is configured as a true HTTP proxy:

Gherkin
Scenario: pathMatches('/api/{path}')
* karate.proceed()

Selective Interception

The real power of proxy mode is combining stubs with forwarding. More specific Scenarios placed before the forwarding Scenario intercept particular requests while everything else passes through:

Gherkin
Feature: Selective proxy

Background:
* def backendUrl = 'https://api.example.com'

Scenario: pathMatches('/api/users/0') && methodIs('get')
# Stub: always return a test user for ID 0
* def response = { id: 0, name: 'Test User', role: 'admin' }

Scenario: pathMatches('/api/health')
# Stub: always healthy, even if real backend is down
* def response = { status: 'UP' }

Scenario: pathMatches('/api/{path}')
# Forward everything else to real backend
* karate.proceed(backendUrl)
# Optionally modify the proxied response
* response.proxied = true

Modifying Proxied Responses

After karate.proceed() returns, the response, responseStatus, and responseHeaders variables contain the backend's response. You can modify any of these before the mock returns the response to the client:

Gherkin
Scenario: pathMatches('/api/{path}')
* karate.proceed('https://api.example.com')
* response.timestamp = new Date().toISOString()
* response.source = 'proxy'

JavaScript Mock Handlers

As an alternative to feature files, you can write mock handlers in plain JavaScript. A JS file is evaluated as a block for each incoming request, with three objects available: request, response, and session.

mock.js
// session persists across requests (like Background variables in feature files)
session.items = session.items || {};
session.counter = session.counter || 1;

if (request.pathMatches('/items') && request.post) {
var id = '' + session.counter++;
var item = request.body;
item.id = id;
session.items[id] = item;
response.status = 201;
response.body = item;
} else if (request.pathMatches('/items/{id}') && request.get) {
var item = session.items[request.pathParams.id];
if (item) {
response.body = item;
} else {
response.status = 404;
response.body = { error: 'Not found' };
}
} else if (request.pathMatches('/items') && request.get) {
response.body = Object.values(session.items);
} else {
response.status = 404;
response.body = { error: 'Unknown path' };
}

Available Objects in JS Handlers

ObjectKey Properties
requestbody, pathMatches(pattern), pathParams, param(name), get, post, put, delete (boolean method checks), proceed(url)
responsestatus, body, headers
sessionPersistent key-value store across requests, equivalent to Background variables

JS handlers are useful when you need tighter integration with Java code or want to avoid Gherkin syntax overhead. For advanced JS handler patterns, see MOCKS.md.

Proxy Mode in JS Handlers

request.proceed(url) forwards the current request to a backend and returns the response — the JS-handler equivalent of karate.proceed(). Omit the URL to target the request's Host header.

proxy.js
// Forward and return backend response as-is
var r = request.proceed('http://real-backend:8080');
response.status = r.status;
response.body = r.body;

// Modify response before returning
var r = request.proceed('http://real-backend:8080');
response.body = { original: r.body, modifiedAt: new Date().toISOString() };

HTML Templating

Karate includes a built-in templating engine based on Thymeleaf syntax but powered by JavaScript expressions. It supports server-rendered HTML with features like th:text, th:if, th:each, session management, and HTMX integration for dynamic partial page updates. This makes it possible to build lightweight web applications or admin interfaces directly alongside your mock servers.

For full templating documentation, see TEMPLATING.md.

Mock Server CLI

The command-line interface provides a quick way to start mock servers without writing any Java or build configuration.

Basic Usage

Terminal
# Start a mock on port 8080
karate mock -m users.feature -p 8080

# Combine multiple mock feature files (scenarios evaluated in order)
karate mock -m users.feature -m orders.feature -p 8080

Watch Mode

Use -W to enable hot-reload. The server automatically picks up changes when you edit the feature file, so you can iterate without restarting:

Terminal
karate mock -m api.feature -p 8080 -W

SSL

Enable HTTPS with --ssl. Karate auto-generates a self-signed certificate if you do not provide one:

Terminal
# Auto-generated certificate
karate mock -m api.feature -p 8443 --ssl

# Custom certificate and key
karate mock -m api.feature -p 8443 --ssl --cert cert.pem --key key.pem

CLI Options Reference

OptionDescription
-m, --mock <file>Mock feature file (repeatable for multiple files)
-p, --port <port>Port number (default: 0 for random available port)
-s, --sslEnable HTTPS with auto-generated certificate
-c, --cert <file>SSL certificate file in PEM format
-k, --key <file>SSL private key file in PEM format
-eSet the karate.env value
-W, --watchWatch mode — hot-reload on file changes
--path-prefix <prefix>URL path prefix to strip from incoming requests

Next Steps