wojtekmach / req

Req is a batteries-included HTTP client for Elixir.
https://hexdocs.pm/req
Apache License 2.0
1.09k stars 117 forks source link

`Req.Test` influences the way integration tests are written. #416

Closed c4710n closed 1 month ago

c4710n commented 1 month ago

In short

Req.Test is good for unit tests without requesting external services.

But, when writing tests which have to request external service, it seems that there's no way to do that.


In detail

In order to describe this issue in more detail, I'd like to use the example provided by the doc of Req.Test.

First, we use following line to make sure the request against a plug stub named MyApp.Weather:

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

Then, we write a test without requesting external service like this:

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

So far so good.

But if I want to add an integration test which ensures "the structure of response of the external service doesn't change":

test "the structure of the response of external service doesn't change" do
   assert {:ok,
            %{
              status: 200, 
              body: %{"celsius" => _}
            }
          } = MyApp.Weather.get_temperature("Krakow, Poland")

   # it will report:
   # (RuntimeError) cannot find mock/stub MyApp.Weather in process #PID<0.519.0>
end

Above test won't work, because we have set a global :plug option in test environment, and there's no way to opt out.

Is there any way to write such type of tests?

wojtekmach commented 1 month ago

There's no easy way to do that at the moment, more details in #385. I'm going to close but feel free to continue discussing this in either issue.