When testing HTTP calls made by your Mix application, your options are to either fire them to the real HTTP endpoint (requires net availability and may count against an API's rate limit) or use a mock (be it is a noun or a verb).
Or you could fire real HTTP requests to a real in promptu webserver instead. Rodeo spawns one-off cowboy webserver instances that reply based on a simple handler API.
(Cowboy… Rodeo… get it?)
- Add
rodeoto your list of dependencies inmix.exs:
def deps do
[{:rodeo, "~> 0.3.0"}]
end- Ensure
rodeois started before your application. Also, you need to addcowboy:
def application do
[applications: [:cowboy, :rodeo]]
endRodeo provides with_webserver that can be used in a test case:
defmodule MyApp.APIClientTest do
use ExUnit.Case
use Rodeo.HTTPCase
test "will start a new cowboy server on a free tcp port" do
with_webserver fn rodeo ->
# rodeo is a %Rodeo{} struct, holding the port of the web server
assert HTTPoison.get!("http://127.0.0.1:#{rodeo.port}/") == "Hello World"
end
# The webserver is torn down again at this point
end
test "uses a custom request handler" do
defmodule Teapot do
use Rodeo.Handler
def body(_req), do: "I'm a teapot"
def status(_req), do: 418
end
with_webserver Teapot, fn rodeo ->
# Rodeo.base_url is a convenience function to
# glue scheme, ip and port together
assert HTTPoison.get!(Rodeo.base_url(rodeo) <> "/earl-grey") == "I'm a teapot"
end
end
endRodeo provides Rodeo.Handler that can be used as a template for custom handlers (see module documentation).
defmodule MyApp.InternalServerError do
use Rodeo.Handler
def status(_), do: 500
def body(_), do: "Oooops!"
def headers(_), do: [{"X-Reason", "Server rolled a 1"}]
end