mariosangiorgio

mariosangiorgio

Mox and GenServer init

I am working on a Phoenix application that also uses a GenServer to fetch some data from a third party API on startup and periodically to refresh the values it got.

I’ve got everything working but then I wanted to add some tests, using a mock in place of the external service and I’m having some problems. I’m using mox following what is described in the documentation and in the blog post.

My GenServer looks like this:

defmodule MyApp.Collector do
  use GenServer
  @api Application.get_env(:my_app, :third_party_api)

  def start_link() do
    GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
  end

  defp fetch_new_state() do
    @third_party_api.lookup()
    # put the data into an Agent
  end

  defp schedule_work() do
    refresh_interval = 10 * 60 * 1000
    Process.send_after(self(), :refresh, refresh_interval)
  end

  def init(state) do
    schedule_work()
    fetch_new_state()
    {:ok, state}
  end

  def handle_info(:refresh, state) do
    schedule_work()
    fetch_new_state()
    {:noreply, state}
  end

  def handle_info(request, state) do
    super(request, state)
  end
end

The problem I have is that the call to fetch_new_state in the init callback would call the mock before I have a chance to set any expectation: (Mox.UnexpectedCallError) no expectation defined for MyApp.ThirdPartyApi.Mock.lookup/0 in process #PID<0.293.0>

I tried to add expectations as early as possible in test_helper.ex, but that didn’t help because mix tries to start all the processes in the supervision tree as part of the mix task, which I believe always happen before any call to test_helper.ex.

I could use mix test --no-start to prevent mix from starting the supervision tree, but that feels wrong because then I would need to manually start all the applications in the correct order.

Another possible workaround is to just schedule some work to be done in init, without calling the api but I’m not very convinced by this approach either.

Is it fine to do some work in the init callback of a GenServer? If it is, how do you handle a scenario like the one I described above?

Most Liked

mbuhot

mbuhot

unless the test case is marked as async.

You can certainly run async tests against the database using the Ecto 2 sandbox.

It’s just not a safe default for Phoenix to run tests async since you may be interacting with stateful named processes.

Where Next?

Popular in Questions Top

shahryarjb
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
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
wernerlaude
In AR this is so simple @articles = current_user.articles How to do in Ecto? def index(conn, _params) do current_user = conn.assig...
New

Other popular topics Top

shahryarjb
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
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
ashish173
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
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement