Skip to content

Sending Messages via Admin API

In addition to stub-triggered responses, WireMock allows you to proactively send messages to connected clients via the Admin API. This is useful for simulating server-initiated events like notifications, broadcasts, or push updates.

Send a message to all WebSocket channels matching a request pattern:

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.matching.RequestPatternBuilder.newRequestPattern;
// Send to all channels on a specific path
SendChannelMessageResult result = wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern().withUrl("/notifications").build(),
new StringEntityDefinition("Server notification!"));
System.out.println("Sent to " + result.getSentCount() + " channels");
// Broadcast to all channels matching a URL pattern
SendChannelMessageResult result = wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern()
.withUrl(urlPathMatching("/users/.*/updates"))
.build(),
new StringEntityDefinition("{\"type\": \"refresh\"}"));

Target channels based on the headers of the initiating request:

// Send to authenticated user channels
SendChannelMessageResult result = wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern()
.withUrl("/ws")
.withHeader("X-User-ID", matching("admin-.*"))
.build(),
new StringEntityDefinition("Admin broadcast"));

Before sending messages, you may want to see which channels are currently connected:

ListMessageChannelsResult result = listAllMessageChannels();
for (MessageChannel channel : result.getChannels()) {
System.out.println("Channel ID: " + channel.getId());
System.out.println("Type: " + channel.getType());
System.out.println("Path: " + channel.getInitiatingRequest().getUrl());
}
wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern().withUrl("/chat").build(),
new StringEntityDefinition("Hello, World!"));
String jsonMessage = """
{
"type": "notification",
"payload": {
"title": "New message",
"content": "You have a new message"
}
}
""";
wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern().withUrl("/notifications").build(),
new StringEntityDefinition(jsonMessage));
SendMessageActionBuilder builder = sendMessage()
.withBodyFromFile("__files/notification.json");
// Use in a stub
messageStubFor(
message()
.triggeredByHttpRequest(
newRequestPattern().withMethod(POST).withUrl("/trigger"))
.willTriggerActions(
builder.onChannelsMatching(
newRequestPattern().withUrl("/notifications"))));

Simulate a server pushing notifications to clients:

@Test
void serverPushNotification() {
// Connect a client
WebSocketClient client = new WebSocketClient();
client.connect("ws://localhost:" + wireMockServer.port() + "/notifications");
// Wait for connection
await().until(client::isConnected);
// Server sends a notification
wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern().withUrl("/notifications").build(),
new StringEntityDefinition("{\"alert\": \"New data available\"}"));
// Verify client received the message
await().until(() -> client.getMessages().contains("{\"alert\": \"New data available\"}"));
}

Send a message to all connected clients:

@Test
void broadcastToAllClients() {
// Connect multiple clients
WebSocketClient client1 = new WebSocketClient();
WebSocketClient client2 = new WebSocketClient();
WebSocketClient client3 = new WebSocketClient();
client1.connect("ws://localhost:" + wm.port() + "/broadcast/user1");
client2.connect("ws://localhost:" + wm.port() + "/broadcast/user2");
client3.connect("ws://localhost:" + wm.port() + "/broadcast/user3");
// Wait for all connections
await().until(() ->
client1.isConnected() && client2.isConnected() && client3.isConnected());
// Broadcast to all /broadcast/* channels
SendChannelMessageResult result = wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern()
.withUrl(urlPathMatching("/broadcast/.*"))
.build(),
new StringEntityDefinition("System announcement"));
assertThat(result.getSentCount(), is(3));
// Verify all clients received the message
await().until(() ->
client1.getMessages().contains("System announcement") &&
client2.getMessages().contains("System announcement") &&
client3.getMessages().contains("System announcement"));
}

Simulate periodic server updates:

@Test
void simulateStockPriceUpdates() {
WebSocketClient client = new WebSocketClient();
client.connect("ws://localhost:" + wm.port() + "/stocks/AAPL");
await().until(client::isConnected);
// Simulate multiple price updates
for (int i = 0; i < 5; i++) {
String priceUpdate = String.format(
"{\"symbol\": \"AAPL\", \"price\": %.2f, \"timestamp\": %d}",
150.00 + Math.random() * 10,
System.currentTimeMillis());
wireMockServer.sendChannelMessage(
ChannelType.WEBSOCKET,
newRequestPattern().withUrl("/stocks/AAPL").build(),
new StringEntityDefinition(priceUpdate));
Thread.sleep(100); // Simulate update interval
}
// Verify client received multiple updates
await().until(() -> client.getMessages().size() >= 5);
}

Use HTTP stubs to trigger WebSocket messages:

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.matching.RequestPatternBuilder.newRequestPattern;
// HTTP endpoint that triggers a WebSocket notification
stubFor(post("/api/orders")
.willReturn(ok("{\"orderId\": \"123\"}")));
// Message stub triggered by the HTTP request
messageStubFor(
message()
.withName("Order notification")
.triggeredByHttpRequest(
newRequestPattern().withMethod(POST).withUrl("/api/orders"))
.willTriggerActions(
sendMessage("{\"type\": \"order_created\", \"orderId\": \"123\"}")
.onChannelsMatching(newRequestPattern().withUrl("/notifications"))));
// Now when POST /api/orders is called, a WebSocket message is sent
EndpointMethodDescription
/__admin/channelsGETList all active message channels
/__admin/channels/sendPOSTSend message to matching channels
{
"type": "websocket",
"initiatingRequest": {
"url": "/path",
"urlPath": "/exact-path",
"urlPattern": "/path/.*",
"urlPathPattern": "/path/.*",
"method": "GET",
"headers": {
"Header-Name": {
"equalTo": "value",
"matches": "pattern.*",
"contains": "substring"
}
}
},
"message": {
"body": {
"data": "message content",
"filePath": "__files/message.json"
}
}
}
{
"sentCount": 3
}

The sentCount indicates how many channels the message was sent to.