Hi all! Deleted the previous post, formatting was very messed up. Apologies!
I’ve got some Mox tests working with some API functions, but the current way I have it organized doesn’t seem quite right to me. Hoping for some guidance and to understand better.
Current module context-
api_calls.ex
houses all of the direct interaction with urls and decoding the whole of JSON responses, i.e.
defp handle_response(url, headers) do
case http_client().get(url, headers) do
{:ok, %{body: body}} ->
Jason.decode!(body)
{:error, reason} ->
{:error, reason}
end
end
defp http_client, do: Application.get_env(:my_app, :http_client)
fetch_users.ex
are the individual functions that call the API/url functions and provide specific transformations of the returned JSON data, clean it up, maps etc. This is where I’m noting the behaviour for Mox to mock. A separate behaviour.ex
file has the callbacks to all the functions here i.e.
@behaviour FetchUsersBehaviour
def get_ids(names, location) do
names
|> Enum.map(&Task.async(fn -> ApiCalls.fetch_id(&1, location) end))
|> Enum.map(&Task.await(&1))
|> Enum.map(& &1["ids"])
end
fetch_users_switch.ex
calls all the functions in fetch_users.ex
, but with the impl layer that Mox uses. i.e.
def get_ids(names, location) do
fetch_impl().get_ids(names, location)
end
defp fetch_impl() do
Application.get_env(:my_app, :users, FetchUsers)
end
fetcher.ex
is the main module that chains/pipes together all the individual functions of fetch_users.ex, but does so by going through fetch_users_switch.ex
.
alias FetchUsersSwitch, as: Fetch
def do_all(name, location) do
name
|> Fetch.get_ids(location)
|> Fetch.foo(location)
|> Fetch.bar(location)
|> Fetch.more(location)
end
My question might be more about subjectivity with how things should be organized, but am I doing this correctly with integrating Mox? Is there a simpler way to do this and Ive just overthought it?