xgeek116
Problem mocking a function when doing unit testing
I’m testing a function that call another function to fetch external data using API calls, here is the main module code :
defmodule MyApp.MyModule.ExternalData do
require Logger
def fetch_external_data(params) do
with {:ok, data} <-
http_get_resource(params["url"], params["headers"]) do
data
else
:error ->
Logger.info("ERROR executing API call to : #{source} with path : #{url} ")
%{}
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 here is my test file :
defmodule MyApp.MyModule.ExternalData.Test do
use ExUnit.Case
# Replace `http_get_resource/2` with a mock function to simulate the HTTP request
def mock_http_get_resource(url, headers) do
case url do
# Simulate a successful request with a 200 status code
"http://valid.com/resource" -> {:ok, %{status_code: 200, body: %{key1: "value1", key2: "value2"}}}
# Simulate a failed request with a 404 status code
"http://invalid.com/resource" -> {:ok, %{status_code: 404, body: "Resource not found"}}
# Simulate a request that times out
"http://timeout.com/resource" -> {:error, :timeout}
end
end
def http_get_resource(url, headers) do
mock_http_get_resource(url, headers)
end
test "fetch_one_external_resource/1" do
# Replace the actual `http_get_resource/2` function with the mock function
alias MyApp.MyModule.ExternalData, as: M
M.http_get_resource = &http_get_resource/2
# Test a successful request
params = %{
"url": "aaa",
"headers": "bbb"
}
assert M.fetch_one_external_resource(params) == %{new_key1: "value1", new_key2: "value2"}
# Test a failed request
params = %{
"url": "aaa",
"headers": "bbb"
}
assert M.fetch_one_external_resource(params) == :error
# Test a request that times out
params = %{
"url": "aaa",
"headers": "bbb"
}
assert M.fetch_one_external_resource(params) == :error
end
end
I’m getting this error :
== Compilation error in file test/fetch_data_test.exs ==
** (CompileError) test/fetch_data_test.exs:26: cannot invoke remote function MyApp.MyModule.ExternalData.http_get_resource/0 inside a match
test/fetch_data_test:23: (module)
(elixir 1.14.2) lib/kernel/parallel_compiler.ex:455: Kernel.ParallelCompiler.require_file/2
(elixir 1.14.2) lib/kernel/parallel_compiler.ex:348: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/7
Any ideas or fix please, I think the problem is in the line M.http_get_resource = &http_get_resource/2
thanks
Most Liked Responses
al2o3cr
That’s not how Elixir modules work, you can’t “reassign” functions in them at runtime.
Consider using one of the mocking libraries like mox or meck that does this correctly.
Alternatively, consider refactoring fetch_external_data into separate functions that can be tested without a live HTTP call.
2
Popular in Questions
In Ruby, I can go:
User.find_by(email: "foobar@email.com").update(email: "hello@email.com")
How can I do something similar in Elixir?
...
New
I have an umbrella app.
Some of the apps inside depend on other apps in the umbrella, unsurprisingly.
I’m writing a test for one of the...
New
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service.
Currently when I de...
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set?
Thanks.
New
Hello, I get Persian date from my client and convert it to normal calendar like this:
def jalali_string_to_miladi_english_number(persi...
New
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
I am trying to run a deploy with docker and I successfully runned with this command:
docker build -t romenigld/blog-prod .
but when I t...
New
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Hi!
Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
Other popular topics
If I have a post route which an argument:
post /my_post_route/:my_param1, MyController.my_post_handler
How would get the post params ...
New
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
I have an umbrella app.
Some of the apps inside depend on other apps in the umbrella, unsurprisingly.
I’m writing a test for one of the...
New
i’m a new one to elixir
which editor can i use
vs code? or atom?
Thanks! :smiley:
New
I tried installing
elixir 1.11.2
erlang 23.3.4
via asdf in my zsh shell. Enabled the versions locally and globally.
When I list them ...
New
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Hello everyone,
Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
Hi there,
I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New









