def deps do
[
{:httpmock, "~> 0.1.5"}
]
end
- Create a router with mocked endpoint in
test/support
defmodule Myapp.APIMockTest do
@moduledoc """
Mock Api
"""
use HTTPMock, behaviour: :httpoison
endpoint "https://jsonplaceholder.typicode.com" do
get "/todos/:id", __MODULE__, :get_todo
get "/users/:id", __MODULE__, :get_user
end
def get_todo(_conn, %{"id" => id}) do
data = ~s({\n \"userId\": #{id},\n \"id\": #{id},\n \"title\": \"delectus aut autem\",\n \"completed\": false\n})
{:ok, %{body: data, status_code: 200}}
end
def get_user(_conn, %{"id" => id}) do
data = ~s({\n "id": #{id},\n "name": "Leanne Graham",\n "username": "Bret",\n "email": "Sincere@april.biz",\n "address": {\n "street": "Kulas Light",\n "suite": "Apt. 556",\n "city": "Gwenborough",\n "zipcode": "92998-3874",\n "geo": {\n "lat": "-37.3159",\n "lng": "81.1496"\n }\n },\n "phone": "1-770-736-8031 x56442",\n "website": "hildegard.org",\n "company": {\n "name": "Romaguera-Crona",\n "catchPhrase": "Multi-layered client-server neural-net",\n "bs": "harness real-time e-markets"\n }\n})
{:ok, %{body: data, status_code: 200}}
end
end
- Using Mimic to mimetize HTTPoison in
test/test_helper.exs
Mimic.copy(HTTPoison)
ExUnit.start()
- use the mimic
test "greets the world" do
Mimic.stub_with(HTTPoison, Myapp.APIMockTest)
assert {:ok, %{ status_code: 200}} = HTTPoison.get("https://jsonplaceholder.typicode.com/todos/1")
end
- Set on top of you module @httpoison const to get env from test.exs
in your file that use httpoison
defmodule MyappWeb.Api.Client do
@moduledoc """
Myapp Web Api Client
"""
@httpoison Application.compile_env(:myapp, :httpoison, HTTPoison)
def get_todo(id) do
@httpoison.get("https://jsonplaceholder.typicode.com/todos/#{id}")
## instead of
# HTTPoison.get("https://jsonplaceholder.typicode.com/todos/#{id}")
end
end
- set env in your config/test.exs
.
.
.
config :myapp, :httpoison, Myapp.APIMockTest
- Use on test
test "greets the world" do
assert {:ok, %{ status_code: 200}} = MyappWeb.Api.Client.get_todos(1)
end
The HTTPMock.State manage the state for your mocked api.
- Set the state in
test/support/my_state.ex
(my_state.ex is an example of namefile)
defmodule Myapp.MyState do
use HTTPMock.State
entity(:todos, default: [], key: :id) ## the field :id is required by now
end
The behaviour HTTPMock.state provide functions to manager state of 'table'
- all()
- all(entity)
- one(entity, id)
- create(entity, params)
- delete(entity, id)
- update(entity, id, params)
- reset()
The reset()
function should be called in setup, before tests, to cleaning state.
:ok = Myapp.MyState.create(:todos, %{id: "uuid", title: "my_title"}) ## the only :id field is required. The other fields, follow your needs
I prefer create a new function on Myapp.MyState, because native create function return :ok, and then I want to return the last created record.
defmodule Myapp.MyState do
...
def new(params) do
id = "uuid_generated"
create(:todos, %{id: id, title: "my_title"})
one(:todos, id)
end
with the Id of record
returned_element= Myapp.MyState.one(:todos,id) ## or nil
with the Id of record
:ok = Myapp.MyState.update(:todos, id, %{title: "updated title"})
with the Id of record
:ok = Myapp.MyState.delete(:todos, id)
with the Id of record
:ok = Myapp.MyState.all(:todos)
with the Id of record
:ok = Myapp.MyState.all()
- Set the HTTPMock.State on Supervisor on test/test_helper.exs.
We provide the
HTTPMock.State.Supervisor
in test/test_helper.exs
HTTPMock.State.Supervisor.start_link([Myapp.MyState])
- Using in your mocked router or in your tests, (rememeber that apply reset before tests) in any file, like test/myapp/some_test.exs
defmodule Myapp.SomeTest do
...
describe "some test" do
setup do
Myapp.MyState.reset()
end
test "testing something" do
assert :ok = Myapp.MyState.create(:todos, %{id: "uuid", title: "my_title"})
assert {:ok, %{body: json_encoded, status_code: 200 } } = MyappWeb.Api.Client.get_todos(1)
assert %{id: "uuid", title: "my_title"} = Jason.decode!(json_encoded)}
end
end
end
in mock route, update to use the state
defmodule Myapp.APIMockTest do
@moduledoc """
Mock Api
"""
use HTTPMock, behaviour: :httpoison
endpoint "https://jsonplaceholder.typicode.com" do
get "/todos/:id", __MODULE__, :get_todo
end
def get_todo(_conn, %{"id" => id}) do
returned_element= Myapp.MyState.one(:todos,id)
data = returned_element |> Jason.encode!() ## Example using jason
{:ok, %{body: data, status_code: 200} }
end
...
end
That is it.