I’m using using mox to help me with my unit testing (for now, I want to mock a function that fetches external API).
my mix.exs :
{:mox, "~> 1.0", only: :test}
My test_helper.exs :
ExUnit.start()
Mox.defmock(MyApp.MockExternalSources, for: MyApp.MyModule.ExternalSources)
My module code (MyApp.MyModule.ExternalSources) :
defmodule MyApp.MyModule.ExternalSources do
@callback http_get_resource(url :: String.t(), headers :: list()) :: {:ok, map()} | :error
@callback fetch_one_external_resource(params :: map()) :: map()
require Logger
def fetch_one_external_resource(params) do
with {:ok, data} <-
http_get_resource(params["url"], params["headers"]) do
do_something(data)
else
:error -> %{}
end
end
def http_get_resource(url, headers) do
case HTTPoison.get(url, headers) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
{:ok, Poison.decode!(body)}
{:ok, %HTTPoison.Response{status_code: 404}} ->
:error
{:error, %HTTPoison.Error{reason: _reason}} ->
:error
end
end
end
And my test module :
defmodule MyApp.MyModule.ExternalSources.Test do
use ExUnit.Case, async: true
import Mox
setup :verify_on_exit!
test "fetch and process external data" do
MyApp.MockExternalSources
|> expect(:http_get_resource, fn _url, _headers ->
{:ok, %{status_code: 200, body: %{key1: "value1", key2: "value2"}}}
end)
params = %{
"url" => "xxx",
"headers" => "yyy"
}
assert MyApp.MyModule.ExternalSources.fetch_one_external_resource(params) ==
%{"new_key1" => "value1", "new_key2" => "value2"}
end
end
But I always get a failed assertion and the behaviour is that the right value (MyApp.MyModule.ExternalSources.fetch_one_external_resource(params)
) is actually calling the external API and getting the real values ignoring my static data in the mock (%{key1: "value1", key2: "value2"}
)
Any help please !