WebSocket Extension
The commercial websocket extension gives WebSocket tests the same session model as the gRPC and Kafka extensions: a karate.channel('websocket') session with send() / pop() / collect(), plus codecs — pluggable encoders/decoders that turn a text-frame protocol such as STOMP into plain JSON your assertions can match on.
Open-source Karate has karate.webSocket() — fine for simple echo-style checks. This page is the commercial extension, which adds the session/codec model, suite-wide defaults, and message collection. They are different APIs; snippets are not interchangeable.
- Either engine JAR —
karate-agent-<version>.jarorkarate-async-<version>.jar(WebSocket is in both). Download from the karate-addons releases. - A license with the
openapientitlement — WebSocket rides that bundle; it is not a separate product. - JDK 21+.
Activate the extension
// Activates WebSocket support. There is no endpoint to set globally — a WebSocket URL
// belongs to the session, so each check sets its own `url`.
boot.ext('websocket');
Optional suite-wide defaults on the same object:
var ws = boot.ext('websocket');
ws.headers = { Authorization: 'Bearer ' + token }; // applied to every session
ws.codec = new (Java.type('io.karatelabs.ext.websocket.JsonTextCodec'))(); // default codec
Write a check
Feature: WebSocket checks
Scenario: raw text echo
* def session = karate.channel('websocket')
* session.url = 'ws://localhost:8090/echo'
* session.start()
* session.send('hello')
* match session.pop() == 'hello'
Scenario: JSON messages via the built-in codec
* def JsonTextCodec = Java.type('io.karatelabs.ext.websocket.JsonTextCodec')
* def session = karate.channel('websocket')
* session.url = 'ws://localhost:8090/echo'
* session.codec = new JsonTextCodec()
* session.start()
* session.send({ type: 'ping', seq: 1 })
* match session.pop() == { type: 'ping', seq: 1 }
Scenario: collect a stream of messages
# count says how many to wait for; collect() blocks until they arrive or the timeout passes
* def session = karate.channel('websocket')
* session.url = 'ws://localhost:8090/echo'
* session.count = 3
* session.start()
* session.send('a')
* session.send('b')
* session.send('c')
* match session.collect() == ['a', 'b', 'c']
Run it: java -jar karate-agent-<version>.jar checks — the HTML report lands in target/karate-reports/.
Configuration reference
Session keys (on karate.channel('websocket')):
| Key | Means |
|---|---|
url | the ws:// or wss:// endpoint — per session, always |
start() | open the connection |
send(msg) | send a message — a string, or an object when a codec encodes it |
count | how many messages collect() waits for (default 1) |
timeout | wait limit in milliseconds |
pop() | take the next message |
collect() | take all messages received (waits for count) |
filter | a JS function — keep only the messages it returns true for |
codec | the wire codec — see below |
headers, header(k, v) | connection headers (e.g. auth) |
subProtocol | the Sec-WebSocket-Protocol value to negotiate |
ssl | boolean or { trustAll: bool }. The default is trust-all (test-friendly); set ssl = false for strict certificate validation |
stop() | close the connection |
Codecs — speak the wire protocol, assert in JSON
A codec implements the WireCodec interface (encode/decode). Two are built in:
io.karatelabs.ext.websocket.RawCodec— the default; text frames pass through as strings, binary frames asbyte[].io.karatelabs.ext.websocket.JsonTextCodec— objects encode to JSON text and decode back.
A custom codec is how you test a protocol layered on WebSocket. The runnable kit includes a complete STOMP example — a small Java class compiled with nothing but the engine jar:
* def StompCodec = Java.type('StompCodec')
* def session = karate.channel('websocket')
* session.url = 'ws://localhost:8091/stomp'
* session.codec = new StompCodec()
* session.start()
* session.send({ command: 'CONNECT', headers: { 'accept-version': '1.2', 'heart-beat': '0,0' } })
* match session.pop().command == 'CONNECTED'
* session.send({ command: 'SUBSCRIBE', headers: { id: 'sub-0', destination: '/topic/greetings' } })
* session.send({ command: 'SEND', headers: { destination: '/app/hello' }, body: { name: 'foo' } })
* def message = session.pop()
* match message.command == 'MESSAGE'
* match message.body.content == 'Hello, foo!'
STOMP frames in, plain JSON out — every assertion is an ordinary match. When a check loads a Java class by name like this, compile it against the engine jar and run with a classpath instead of -jar (in the kit, the codec lives under server/):
javac -cp karate-agent-<version>.jar -d server-classes server/StompCodec.java
java -cp "karate-agent-<version>.jar:server-classes" io.karatelabs.Main run checks
The 0.x session.adapter / WebsocketAdapter / io.karatelabs.websocket.JsonAdapter API is gone. The replacement is session.codec with the WireCodec interface, and the built-ins under io.karatelabs.ext.websocket.* as above. Lifecycle hooks (onStart / onStop / onMessage) moved to the separate WebsocketLifecycle mix-in.
Runnable example
A complete, CI-verified project — echo server, STOMP broker, the StompCodec source, checks and boot file — is at karate-agent-examples/websocket, with its live report. If a snippet on this page ever disagrees with that kit, the kit is the one gated by CI.
The openapi entitlement that unlocks WebSocket is part of Karate Agent — the AI-native engine that adds a served console, API governance and requirements traceability over the same feature files. See the enterprise overview.
See Also
- WebSocket (open source) — the
karate.webSocket()API for simple checks - gRPC Testing · Kafka Testing — the same session model over other protocols
- Extensions — how
karate-boot.jsandboot.ext(...)work