FakeServer
FakeServer makes it easy to create mocks for HTTP servers in your tests. It integrates very well with ExUnit, but can also be used as a standalone server.
Following this README you will see some basic examples of usage. More details can be found in the documentation available on Hexdocs.
Important: This README follows the master branch, that may not have been published yet. Therefore, information contained herein may not be present in the docs.
Installation
FakeServer is available on Hex. All you have to do is to add it to mix.exs as a test dependency.
def deps do
[{:fake_server, "~> 1.2", only: :test}]
end
Start fake_server application on test/test_helper.exs
{:ok, _} = Application.ensure_all_started(:fake_server)
ExUnit integration
To use FakeServer together with ExUnit, simply write your tests using the test_with_server macro.
Running a test with a server
test_with_server, starts an HTTP server, initially without any route configured (that is, any request will be replied with 404).
test_with_server "server will always reply 404 without any route configured", do
response = HTTPoison.get! FakeServer.address <> "/"
assert response.status_code == 404
response = HTTPoison.get! FakeServer.address <> "/any/route"
assert response.status_code == 404
response = HTTPoison.get! FakeServer.address <> "/another/route"
assert response.status_code == 404
end
Adding routes
You can add routes to your server through the route macro.
A route can reply a request in 3 ways:
- directly returning the a
[%FakeServer.HTTP.Response{}](https://hexdocs.pm/fake_server/FakeServer.HTTP.Response.html)structure; - iterating a list of
[%FakeServer.HTTP.Response{}](https://hexdocs.pm/fake_server/FakeServer.HTTP.Response.html)structures; - querying a
[FakeController](https://hexdocs.pm/fake_server/FakeController.html).
With a single response
# test/my_app/some_module_test.exs
describe "with a single response element" do
test_with_server "reply with this element once and then uses a default response" do
route "/test", do: Response.bad_request
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 400
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 200
assert response.body == "This is a default response from FakeServer"
end
test_with_server "this default response can be configured", [default_response: Response.forbidden] do
route "/test", do: Response.bad_request
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 400
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 403
end
end
With a list of responses
# test/my_app/some_module_test.exs
describe "with a list of responses" do
test_with_server "responds with the first element until the list empties, and then uses a default response" do
route "/test", do: [Response.ok, Response.not_found, Response.bad_request]
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 200
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 404
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 400
# reply the default_response when the list empties
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 200
assert response.body == "This is a default response from FakeServer"
end
test_with_server "this default response can be configured", [default_response: Response.forbidden] do
route "/test", do: []
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 403
response = HTTPoison.get! FakeServer.address <> "/test"
assert response.status_code == 403
end
end
With FakeControllers
With FakeControllers you can analyze the content of the request and choose the type of response dynamically.
A controller is a special function that is executed every time a route configured with it receives a request.
# test/support/fake_controllers.ex
# Create a module with your controllers and use the
# FakeController.__using__ macro on this module
defmodule FakeServer.Integration.FakeControllers do
use FakeController
# Controller names must end in _controller
# Also, they receive a single argument
# They must return an %FakeServer.HTTP.Response struct
def query_string_controller(conn) do
if :cowboy_req.qs_val("token", conn) |> elem(0) == "1234" do
FakeServer.HTTP.Response.ok
else
FakeServer.HTTP.Response.unauthorized
end
end
end
# test/my_app/some_test.exs
test_with_server "evaluates FakeController and reply accordingly" do
# Every time a request arrives at root path, the controller
# will be executed to determine which response should be given
# Note that _controller is not needed on the controller name this time!
route "/", do: use_controller :query_string
response = HTTPoison.get! FakeServer.address <> "/"
assert response.status_code == 401
response = HTTPoison.get! FakeServer.address <> "/?token=1234"
assert response.status_code == 200
end
Server configuration
The test_with_server macro accepts a keyword list with arguments to the server that will be created.
# test/my_app/some_test.exs
test_with_server "accepts the port argument to configure a custom port for the server", [port: 5001] do
assert FakeServer.address == "127.0.0.1:5001"
route "/", do: Response.bad_request
response = HTTPoison.get! "127.0.0.1:5001" <> "/"
assert response.status_code == 400
end
test_with_server "accepts the default_response argument to configure the server default response", [default_response: Response.bad_request] do
route "/", do: []
response = HTTPoison.get! FakeServer.address <> "/"
assert response.status_code == 400
end