# Test Using Mox

To mock HTTP requests in your tests using Mox with the Tesla HTTP client,
follow these steps:

## 1. Define a Mock Adapter

First, define a mock adapter that implements the Tesla.Adapter behaviour. This
adapter will intercept HTTP requests during testing.

Create a file at `test/support/mocks.ex`:

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

## 2. Configure the Mock Adapter for Tests

In your `config/test.exs` file, configure Tesla to use the mock adapter you
just defined:

```elixir
# config/test.exs
config :tesla, adapter: MyApp.MockAdapter
```

If you are not using the global adapter configuration, ensure that your Tesla
client modules are configured to use `MyApp.MockAdapter` during tests.

## 3. Set Up Mocking in Your Tests

Create a test module, for example `test/demo_test.exs`, and set up `Mox` to
define expectations and verify them:

```elixir
defmodule MyApp.FeatureTest do
  use ExUnit.Case, async: true

  import Mox
  import Tesla.Test

  setup :set_mox_from_context
  setup :verify_on_exit!

  test "example test" do
    #--------- Given - Stubs and Preconditions
    # Expect a single HTTP request to be made and return a JSON response
    expect_tesla_call(
      times: 1,
      returns: json(%Tesla.Env{status: 200}, %{id: 1})
    )

    #--------- When - Run the code under test
    # Make the HTTP request using Tesla
    # Mimic a use case where we create a user
    assert :ok = create_user!(%{username: "johndoe"})

    #--------- Then - Assert postconditions
    # Verify that the HTTP request was made and matches the expected parameters
    assert_received_tesla_call(env, [])
    assert env.status == 200
    assert env.method == :post
    assert env.url == "https://acme.com/users"
    # ...

    # Or you can verify the entire `t:Tesla.Env.t/0` using something like this:
    assert_tesla_env(env, %Tesla.Env{
      method: :post,
      url: "https://acme.com/users",
      body: %{username: "johndoe"},
      status: 200,
    })

    # Verify that the mailbox is empty, indicating no additional requests were
    # made and all messages have been processed
    assert_tesla_empty_mailbox()
  end

  defp create_user!(body) do
    # ...
    Tesla.post!("https://acme.com/users", body)
    # ...
    :ok
  end
end
```

## 4. Run Your Tests

When you run your tests with `mix test`, all HTTP requests made by Tesla will
be intercepted by `MyApp.MockAdapter`, and responses will be provided based
on your `Mox` expectations.
