Q32 of 40 · Karate
How do you handle WebSockets in Karate?
Short answer
Short answer: Use * def ws = karate.webSocket(url, messageHandler) to open a connection, ws.send(message) to send frames, and karate.listen(timeout) to receive a message. The handler function is called on each incoming message and can set a Karate variable to resolve the listen call. Assert on the received message with normal match syntax.
Detail
Karate's WebSocket support is built in (since 1.0) via the karate.webSocket() API:
# Open a WebSocket connection
* def handler = function(msg){ karate.signal(msg) }
* def ws = karate.webSocket('wss://api.example.com/ws/prices', handler)
# Send a subscription message
* ws.send('{ "action": "subscribe", "channel": "BTC-USD" }')
# Wait for a message (max 5 seconds)
* def message = karate.listen(5000)
# Assert the received message
* match message == { channel: 'BTC-USD', price: '#number', timestamp: '#string' }
# Close the connection
* ws.close()
karate.signal: called from inside the handler to pass the received message back to the scenario. karate.listen(timeout) blocks until signal is called (or timeout).
Multiple messages: to receive N messages, accumulate them in an array inside the handler and signal when the count reaches N.
STOMP over WebSocket (Spring Boot): Karate doesn't have native STOMP support. Use the stomp.js library via embedded JavaScript, or test STOMP endpoints via the HTTP-based fallback (polling endpoint) if the API exposes one.
Testing presence and real-time features: WebSocket tests are inherently time-sensitive — set realistic timeouts (5-30s) and handle the case where the message arrives before the listen() call (use a shared variable in the handler).
// EXAMPLE
websocket-test.feature
Feature: Real-time price feed via WebSocket
Scenario: Subscribe to BTC price feed and receive first update
* def received = []
* def handler = function(msg) {
karate.log('received:', msg);
received.push(msg);
if (received.length >= 1) {
karate.signal(received[0]); // signal on first message
}
}
# Open connection
* def ws = karate.webSocket('wss://api.example.com/ws/prices', handler)
# Subscribe
* ws.send('{ "action": "subscribe", "channel": "BTC-USD" }')
# Wait up to 10s for first price update
* def firstUpdate = karate.listen(10000)
# Assert message structure
* match firstUpdate == {
channel: 'BTC-USD',
price: '#number',
bid: '#number',
ask: '#number',
timestamp: '#string'
}
* match firstUpdate.price == '#? _ > 0'
# Unsubscribe and close
* ws.send('{ "action": "unsubscribe", "channel": "BTC-USD" }')
* ws.close()