Testing multiple API calls in a function chain with Mox

1.6k Views Asked by At

I'm trying to test that I'm transforming the data coming back from a third party api correctly. I'm hitting some trouble with Mox because I need to hit two separate endpoints during the data transformation. Let me explain more clearly by posting code:

Test:

  test "players/0 return all active players" do
    Statcasters.SportRadarNbaApi.ClientMock
    |> expect(:league_hierarchy, fn ->
      {:ok, league_hierarchy_map()}
    end)

    Statcasters.SportRadarNbaApi.ClientMock
    |> expect(:team_profile, fn _ ->
      {:ok, team_profile_map()}
    end)


    assert Statcasters.Sports.Nba.get_players() == ["Kevon Looney", "Patrick McCaw"]
  end

Code:

  def get_players do
    with {:ok, hierarchy} <- @sport_radar_nba_api.league_hierarchy,
         team_ids <- get_team_ids(hierarchy),
         players <- get_team_players(team_ids)
    do
      IO.inspect players
    end
  end

  defp get_team_players(team_ids) do
    for team_id <- team_ids do
      {:ok, team} = @sport_radar_nba_api.team_profile(team_id)
    end
  end

Ignore the fact that the code as written won't actually pass the test. It's the test failure that I'm trying to figure out.

Problem:

The second api call team_profile gets called twice in the test because I iterate through two team_ids and for each team_id I call the API. This is expected but the test is not prepared for that because I'm getting this error.

Error:

** (Mox.UnexpectedCallError) expected Statcasters.SportRadarNbaApi.ClientMock.team_profile/1 to be called once but it has been called 2 times in process #PID<0.410.0>

This is correct. I do call it twice, but how do I setup the test to expect that this API endpoint is going to be called twice?

1

There are 1 best solutions below

1
On BEST ANSWER

The third optional argument to expect is the number of times the mocked function should be called. In this case, just set it to 2:

Statcasters.SportRadarNbaApi.ClientMock
|> expect(:team_profile, 2, fn _ ->
  {:ok, team_profile_map()}
end)