View Source Req.Test (req v0.4.11)

Functions for creating test stubs.

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.

"Mocks Aren't Stubs" by Martin Fowler

Req has built-in support for stubs via :plug, :adapter, and (indirectly) :base_url options. This module enhances these capabilities by providing:

Example

Imagine we're building an app that displays weather for a given location using an HTTP weather service:

defmodule MyApp.Weather do
  def get_rating(location) do
    case get_temperature(location) do
      {:ok, %{status: 200, body: %{"celsius" => celsius}}} ->
        cond do
          celsius < 18.0 -> {:ok, :too_cold}
          celsius < 30.0 -> {:ok, :nice}
          true -> {:ok, :too_hot}
        end

      _ ->
        :error
    end
  end

  def get_temperature(location) do
    [
      base_url: "https://weather-service"
    ]
    |> Keyword.merge(Application.get_env(:myapp, :weather_req_options, []))
    |> Req.request(options)
  end
end

We configure it for production:

# config/runtime.exs
config :myapp, weather_req_options: [
  auth: {:bearer, System.fetch_env!("MYAPP_WEATHER_API_KEY")}
]

In tests, instead of hitting the network, we make the request against a plug stub named MyApp.Weather:

# config/test.exs
config :myapp, weather_req_options: [
  plug: {Req.Test, MyApp.Weather}
]

Now we can control our stubs in concurrent tests:

use ExUnit.Case, async: true

test "nice weather" do
  Req.Test.stub(MyApp.Weather, fn conn ->
    Req.Test.json(conn, %{"celsius" => 25.0})
  end)

  assert MyApp.Weather.get_rating("Krakow, Poland") == {:ok, :nice}
end

Summary

Functions

Sends JSON response.

Returns the stub created by stub/2.

Creates a stub with given name and value.

Functions

Sends JSON response.

Examples

iex> plug = fn conn ->
...>   Req.Test.json(conn, %{celsius: 25.0})
...> end
iex>
iex> resp = Req.get!(plug: plug)
iex> resp.headers["content-type"]
["application/json; charset=utf-8"]
iex> resp.body
%{"celsius" => 25.0}

Returns the stub created by stub/2.

Creates a stub with given name and value.

This function allows stubbing any value and later access it with stub/1. It is safe to use in concurrent tests.

See module documentation for more examples.

Examples

iex> Req.Test.stub(MyStub, :foo)
iex> Req.Test.stub(MyStub)
:foo
iex> Task.async(fn -> Req.Test.stub(MyStub) end) |> Task.await()
:foo