Skip to content

Commit

Permalink
feat: add mox integration test support
Browse files Browse the repository at this point in the history
  • Loading branch information
yordis committed Oct 23, 2024
1 parent 1baedf2 commit 8b35f71
Show file tree
Hide file tree
Showing 8 changed files with 471 additions and 12 deletions.
67 changes: 67 additions & 0 deletions guides/explanations/1.testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,70 @@ end
```

For more details, refer to the `Tesla.Mock` module documentation.



# PENDING

Integrate `Tesla` with `Mox`. Provides helpers to expect calls on the
adapter and assert on the received calls.

## Getting started

Make sure to have `Mox` setup in your project. We are assuming that you have
experience with `Mox`. Please verify that `Mox` is properly setup in your
project.

Define the `Mox` mocked adapter

```elixir
# test/support/mocks.ex
Mox.defmock(Test.TeslaAdapterMock, for: Tesla.Adapter)
```

Assuming that you are using the global adapter, set the mocked adapter in
your `config/test.exs` configuration:

```elixir
# config/test.exs
config :tesla, adapter: Test.TeslaAdapterMock
```

If you are not using the global adapter, please configure your setup to use
the `Test.TeslaAdapterMock` adapter, in this case.

Require this module in your test case, in order to use the macros provided
by this module:

defmodule MyAppTest do
use ExUnit.Case, async: true
require Tesla.TeslaMox

# ...
end

Expect that a given adapter receives a call, and make the call:

defmodule MyAppTest do
use ExUnit.Case, async: true
require Tesla.TeslaMox, as: TeslaMox

test "creating a user" do
Tesla.TeslaMox.expect_tesla_call(
times: 2,
returns: %Tesla.Env{status: 200}
)

assert :ok = create_user!()

TeslaMox.assert_received_tesla_call(env)
assert env.status == 200
end

defp create_user! do
# ...
Tesla.post!("https://acme.com/users")
# ...
:ok
end
end
24 changes: 17 additions & 7 deletions lib/tesla/adapter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,20 @@ defmodule Tesla.Adapter do
"""

@typedoc """
Unstructured data passed to the adapter using `opts[:adapter]`.
"""
@type options :: any()

@doc """
Invoked when a request runs.
## Arguments
- `env` - `Tesla.Env` struct that stores request/response data
- `options` - middleware options provided by user
- `env` - `t:Tesla.Env.t/0` struct that stores request/response data.
- `options` - middleware options provided by user.
"""
@callback call(env :: Tesla.Env.t(), options :: any) :: Tesla.Env.result()
@callback call(env :: Tesla.Env.t(), options :: options()) :: Tesla.Env.result()

@doc """
Helper function that merges all adapter options.
Expand All @@ -70,10 +75,15 @@ defmodule Tesla.Adapter do
## Precedence rules
- config from `opts` overrides config from `defaults` when same key is
encountered.
- config from `env` overrides config from both `defaults` and `opts` when same
key is encountered.
The options are merged in the following order of precedence (highest to lowest):
1. Options from `env.opts[:adapter]` (highest precedence).
2. Options provided to the adapter from `Tesla.client/2`.
3. Default options (lowest precedence).
This means that options specified in `env.opts[:adapter]` will override any
conflicting options from the other sources, allowing for fine-grained control
on a per-request basis.
"""
@spec opts(Keyword.t(), Tesla.Env.t(), Keyword.t()) :: Keyword.t()
def opts(defaults \\ [], env, opts) do
Expand Down
4 changes: 2 additions & 2 deletions lib/tesla/mock.ex
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ defmodule Tesla.Mock do
import Tesla.Mock
mock fn
%{url: "/ok"} -> text(%{"some" => "data"})
%{url: "/404"} -> text(%{"some" => "data"}, status: 404)
%{url: "/ok"} -> text("200 ok")
%{url: "/404"} -> text("404 not found", status: 404)
end
"""
@spec text(body :: term, opts :: response_opts) :: Tesla.Env.t()
Expand Down
Loading

0 comments on commit 8b35f71

Please sign in to comment.