WebSocket Mocking
MockForge provides comprehensive WebSocket connection mocking with support for both scripted replay scenarios and interactive real-time communication. This enables testing of WebSocket-based applications, real-time APIs, and event-driven systems.
WebSocket Mocking Modes
MockForge supports two primary WebSocket mocking approaches:
1. Replay Mode (Scripted)
Pre-recorded message sequences that play back on schedule, simulating server behavior with precise timing control.
2. Interactive Mode (Real-time)
Dynamic responses based on client messages, enabling complex interactive scenarios and stateful communication.
Configuration
Basic WebSocket Setup
# Start MockForge with WebSocket support
mockforge serve --ws-port 3001 --ws-replay-file ws-scenario.jsonl
Environment Variables
# WebSocket configuration
MOCKFORGE_WS_ENABLED=true # Enable WebSocket support (default: false)
MOCKFORGE_WS_PORT=3001 # WebSocket server port
MOCKFORGE_WS_BIND=0.0.0.0 # Bind address
MOCKFORGE_WS_REPLAY_FILE=path/to/file.jsonl # Path to replay file
MOCKFORGE_WS_PATH=/ws # WebSocket endpoint path (default: /ws)
MOCKFORGE_RESPONSE_TEMPLATE_EXPAND=true # Enable template processing
Command Line Options
mockforge serve \
--ws-port 3001 \
--ws-replay-file examples/ws-demo.jsonl \
--ws-path /websocket
Replay Mode
Replay mode uses JSONL-formatted files to define scripted message sequences with precise timing control.
Replay File Format
Each line in the replay file is a JSON object with the following structure:
{
"ts": 0,
"dir": "out",
"text": "Hello, client!",
"waitFor": "^CLIENT_READY$"
}
Field Definitions
ts
(number, required): Timestamp offset in milliseconds from connection startdir
(string, required): Message direction"out"
- Message sent from server to client"in"
- Expected message from client (for validation)
text
(string, required): Message content (supports templates)waitFor
(string, optional): Regular expression to wait for before proceeding
Basic Replay Example
{"ts":0,"dir":"out","text":"Welcome to MockForge WebSocket server","waitFor":"^HELLO$"}
{"ts":1000,"dir":"out","text":"Connection established"}
{"ts":2000,"dir":"out","text":"Sending data: 42"}
{"ts":3000,"dir":"out","text":"Goodbye"}
Advanced Replay Features
Template Support
{"ts":0,"dir":"out","text":"Session {{uuid}} started at {{now}}"}
{"ts":1000,"dir":"out","text":"Random value: {{randInt 1 100}}"}
{"ts":2000,"dir":"out","text":"Future event at {{now+5m}}"}
Interactive Elements
{"ts":0,"dir":"out","text":"Please authenticate","waitFor":"^AUTH .+$"}
{"ts":100,"dir":"out","text":"Authentication successful"}
{"ts":200,"dir":"out","text":"Choose option (A/B/C)","waitFor":"^(A|B|C)$"}
Complex Message Structures
{"ts":0,"dir":"out","text":"{\"type\":\"welcome\",\"user\":{\"id\":\"{{uuid}}\",\"name\":\"John\"}}"}
{"ts":1000,"dir":"out","text":"{\"type\":\"data\",\"payload\":{\"items\":[{\"id\":1,\"value\":\"{{randInt 10 99}}\"},{\"id\":2,\"value\":\"{{randInt 100 999}}\"}]}}"}
Replay File Management
Creating Replay Files
# Record from live WebSocket connection
# (Feature in development - manual creation for now)
# Create from application logs
# Extract WebSocket messages and convert to JSONL format
# Generate programmatically
node -e "
const fs = require('fs');
const messages = [
{ts: 0, dir: 'out', text: 'HELLO', waitFor: '^HI$'},
{ts: 1000, dir: 'out', text: 'DATA: 42'}
];
fs.writeFileSync('replay.jsonl', messages.map(JSON.stringify).join('\n'));
"
Validation
# Validate replay file syntax
node -e "
const fs = require('fs');
const lines = fs.readFileSync('replay.jsonl', 'utf8').split('\n');
lines.forEach((line, i) => {
if (line.trim()) {
try {
const msg = JSON.parse(line);
if (!msg.ts || !msg.dir || !msg.text) {
console.log(\`Line \${i+1}: Missing required fields\`);
}
} catch (e) {
console.log(\`Line \${i+1}: Invalid JSON\`);
}
}
});
console.log('Validation complete');
"
Interactive Mode
Interactive mode enables dynamic responses based on client messages, supporting complex conversational patterns and state management.
Basic Interactive Setup
{"ts":0,"dir":"out","text":"What is your name?","waitFor":"^NAME .+$"}
{"ts":100,"dir":"out","text":"Hello {{request.ws.lastMessage.match(/^NAME (.+)$/)[1]}}!"}
State Management
{"ts":0,"dir":"out","text":"Welcome! Type 'START' to begin","waitFor":"^START$"}
{"ts":100,"dir":"out","text":"Game started. Score: 0","state":"playing"}
{"ts":200,"dir":"out","text":"Choose: ROCK/PAPER/SCISSORS","waitFor":"^(ROCK|PAPER|SCISSORS)$"}
{"ts":300,"dir":"out","text":"You chose {{request.ws.lastMessage}}. I chose ROCK. You win!","waitFor":"^PLAY_AGAIN$"}
Conditional Logic
{"ts":0,"dir":"out","text":"Enter command","waitFor":".+","condition":"{{request.ws.message.length > 0}}"}
{"ts":100,"dir":"out","text":"Processing: {{request.ws.message}}"}
{"ts":200,"dir":"out","text":"Command completed"}
Testing WebSocket Connections
Using WebSocket Clients
Node.js Client
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:3001/ws');
ws.on('open', () => {
console.log('Connected to MockForge WebSocket');
ws.send('CLIENT_READY');
});
ws.on('message', (data) => {
const message = data.toString();
console.log('Received:', message);
// Auto-respond to common prompts
if (message.includes('ACK')) {
ws.send('ACK');
}
if (message.includes('CONFIRMED')) {
ws.send('CONFIRMED');
}
if (message.includes('AUTH')) {
ws.send('AUTH token123');
}
});
ws.on('close', () => {
console.log('Connection closed');
});
ws.on('error', (err) => {
console.error('WebSocket error:', err);
});
Browser JavaScript
const ws = new WebSocket('ws://localhost:3001/ws');
ws.onopen = () => {
console.log('Connected');
ws.send('CLIENT_READY');
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
// Handle server messages
};
ws.onclose = () => {
console.log('Connection closed');
};
Command Line Tools
# Using websocat
websocat ws://localhost:3001/ws
# Using curl (WebSocket support experimental)
curl --include \
--no-buffer \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==" \
--header "Sec-WebSocket-Version: 13" \
ws://localhost:3001/ws
Automated Testing
#!/bin/bash
# test-websocket.sh
echo "Testing WebSocket connection..."
# Test with Node.js
node -e "
const WebSocket = require('ws');
const ws = new WebSocket('ws://localhost:3001/ws');
ws.on('open', () => {
console.log('✓ Connection established');
ws.send('CLIENT_READY');
});
ws.on('message', (data) => {
console.log('✓ Message received:', data.toString());
ws.close();
});
ws.on('close', () => {
console.log('✓ Connection closed successfully');
process.exit(0);
});
ws.on('error', (err) => {
console.error('✗ WebSocket error:', err);
process.exit(1);
});
// Timeout after 10 seconds
setTimeout(() => {
console.error('✗ Test timeout');
process.exit(1);
}, 10000);
"
Advanced Features
Connection Pooling
# Support multiple concurrent connections
MOCKFORGE_WS_MAX_CONNECTIONS=100
MOCKFORGE_WS_CONNECTION_TIMEOUT=30000
Message Filtering
{"ts":0,"dir":"in","text":".*","filter":"{{request.ws.message.startsWith('VALID_')}}"}
{"ts":100,"dir":"out","text":"Valid message received"}
Error Simulation
{"ts":0,"dir":"out","text":"Error occurred","error":"true","code":1006}
{"ts":100,"dir":"out","text":"Connection will close","close":"true"}
Binary Message Support
{"ts":0,"dir":"out","text":"AQIDBAU=","binary":"true"}
{"ts":1000,"dir":"out","text":"Binary data sent"}
Integration Patterns
Real-time Applications
- Chat Applications: Mock user conversations and bot responses
- Live Updates: Simulate real-time data feeds and notifications
- Gaming: Mock multiplayer game state and player interactions
API Testing
- WebSocket APIs: Test GraphQL subscriptions and real-time queries
- Event Streams: Mock server-sent events and push notifications
- Live Dashboards: Simulate real-time metrics and monitoring data
Development Workflows
- Frontend Development: Mock WebSocket backends during UI development
- Integration Testing: Test WebSocket handling in microservices
- Load Testing: Simulate thousands of concurrent WebSocket connections
Best Practices
Replay File Organization
- Modular Files: Break complex scenarios into smaller, focused replay files
- Version Control: Keep replay files in Git for collaboration
- Documentation: Comment complex scenarios with clear descriptions
- Validation: Always validate replay files before deployment
Performance Considerations
- Message Volume: Limit concurrent connections based on system resources
- Memory Usage: Monitor memory usage with large replay files
- Timing Accuracy: Consider system clock precision for time-sensitive scenarios
- Connection Limits: Set appropriate connection pool sizes
Security Considerations
- Input Validation: Validate all client messages in interactive mode
- Rate Limiting: Implement connection rate limits for production
- Authentication: Mock authentication handshakes appropriately
- Data Sanitization: Avoid exposing sensitive data in replay files
Debugging Tips
- Verbose Logging: Enable detailed WebSocket logging for troubleshooting
- Connection Monitoring: Track connection lifecycle and message flow
- Replay Debugging: Step through replay files manually
- Client Compatibility: Test with multiple WebSocket client libraries
Troubleshooting
Common Issues
Connection fails: Check that WebSocket port is not blocked by firewall
Messages not received: Verify replay file path and JSONL format
Templates not expanding: Ensure MOCKFORGE_RESPONSE_TEMPLATE_EXPAND=true
Timing issues: Check system clock and timestamp calculations
Debug Commands
# Check WebSocket port
netstat -tlnp | grep :3001
# Monitor connections
ss -tlnp | grep :3001
# Test basic connectivity
curl -I http://localhost:3001/health # If HTTP health endpoint exists
Log Analysis
# View WebSocket logs
tail -f mockforge.log | grep -i websocket
# Count connections
grep "WebSocket connection" mockforge.log | wc -l
# Find errors
grep -i "websocket.*error" mockforge.log
For detailed implementation guides, see:
- Replay Mode - Advanced scripted scenarios
- Interactive Mode - Dynamic real-time communication