# WebSocketMock
[](https://hex.pm/packages/websocket_mock)
[](https://hexdocs.pm/websocket_mock)
Lightweight WebSocket mock server and mock client for testing.
## Installation
Add `websocket_mock` to your test dependencies in `mix.exs`:
```elixir
def deps do
[
{:websocket_mock, "~> 0.3.0", only: :test}
]
end
```
## Quick Start
```elixir
iex> alias WebSocketMock.MockServer
iex> alias WebSocketMock.MockClient
iex>
iex> {:ok, server} = MockServer.start()
iex> {:ok, client} = MockClient.start(server.url)
iex> MockServer.is_connected?(server)
true
iex> MockServer.num_connections(server)
1
iex> [%{client_id: client_id}] = MockServer.list_clients(server)
iex> MockServer.send_message(server, client_id, {:text, "Hello!"})
:ok
iex> MockClient.send_message(client, {:text, "world"})
:ok
iex>
iex> MockServer.received_messages(server)
[{:text, "world"}]
iex> MockClient.received_messages(client)
[{:text, "Hello!"}]
iex> alias WebSocketMock.MockServer
iex> alias WebSocketMock.MockClient
iex>
iex> {:ok, server} = MockServer.start()
iex> {:ok, client} = MockClient.start(server.url)
iex> # Set up automatic replies
iex> MockServer.reply_with(server, {:text, "ping"}, {:text, "pong"})
iex> # Also works with functions as filters
iex> MockServer.reply_with(server, fn {opcode, msg} -> msg == "ping" end, {:text, "pong"})
iex>
iex> MockClient.send_message(client, {:text, "ping"})
iex> Process.sleep(20)
iex> MockClient.received_messages(client)
[{:text, "pong"}]
iex> # Mockserver accepts callbacks which run before sending the reply
iex> MockServer.reply_with(server, "ping", fn {opcode, msg} -> {opcode, msg <> " pong"} end)
iex> MockClient.send_message(client, {:text, "ping"})
iex> Process.sleep(20)
iex> MockClient.received_messages(client)
[{:text, "pong"}, {:text, "ping pong"}]
```
## Usage in Tests
```elixir
defmodule MyAppTest do
use ExUnit.Case
alias WebSocketMock.MockServer
alias WebSocketMock.MockClient
setup do
{:ok, server} = MockServer.start()
on_exit(fn -> MockServer.stop(server) end)
%{server: server}
end
test "websocket client connects and receives messages", %{server: server} do
{:ok, client} = MockClient.start(server.url)
[%{client_id: client_id}] = MockServer.list_clients(server)
MockServer.send_message(server, client_id, {:text, "test message"})
assert MockClient.received_messages(client) == [{:text, "test message"}]
end
test "client sends message to server", %{server: server} do
{:ok, client} = MockClient.start(server.url)
MockClient.send_message(client, {:text, "Hello Server!"})
assert MockServer.received_messsages(server) == [{:text, "Hello Server!"}]
end
test "client handles response", %{server: server} do
{:ok, client} = MockClient.start(server.url)
MockServer.reply_with(server, {:text, "hello"}, {:text, "world"})
MockServer.reply_with(server, {:text, "buy"}, {:text, "see ya"})
MockClient.send_message(client, {:text, "hello"})
assert MockClient.received_messages(client) == [{:text, "world"}]
MockClient.send_message(client, {:text, "buy"})
assert {:text, "see ya"} in MockClient.received_messages(client)
end
end
```
## Documentation
Full documentation is available at [https://hexdocs.pm/websocket_mock](https://hexdocs.pm/websocket_mock).
## Known Issues
- Tests are flaky because of the asynchronous nature of the requests. Needs improvement.
- The mock server currently crashes on start when the randomly selected port is already in use.
## License
MIT License. See [LICENSE](LICENSE) for details.