Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Doctest of a functions that have side effects
defmodule MyApp.WeatherAPI do
@callback temp(MyApp.LatLong.t()) :: {:ok, integer()}
@callback humidity(MyApp.LatLong.t()) :: {:ok, integer()}
def temp(lat_long), do: impl().temp(lat_long)
def humidity(lat_long), do: impl().humidity(lat_long)
defp impl, do: Application.get_env(:my_app, :weather, MyApp.ExternalWeatherAPI)
end
defmodule MyApp.HumanizedWeather do
@doc """
Displays current temperature at the given coordinates
## Examples
iex> HumanizedWeather.display_temp({50.06, 19.94})
"Current temperature is 30 degrees"
iex> HumanizedWeather.display_temp({102.06, 19.94})
** (RuntimeError) latitude must be in the range of -90 to 90 degrees
"""
def display_temp({lat, long}) do
case MyApp.WeatherAPI.temp({lat, long}) do
{:ok, temp} -> "Current temperature is #{temp} degrees"
{:error, reason} -> raise reason
end
end
@doc """
Displays current humidity at the given coordinates
## Examples
iex> HumanizedWeather.display_humidity({50.06, 19.94})
"Current humidity is 60%"
"""
def display_humidity({lat, long}) do
{:ok, humidity} = MyApp.WeatherAPI.humidity({lat, long})
"Current humidity is #{humidity}%"
end
end
defmodule MyApp.HumanizedWeatherTest do
use ExUnit.Case, async: true
import Mox
alias MyApp.HumanizedWeather
setup :verify_on_exit!
describe "display_temp/1" do
doctest MyApp.HumanizedWeather, only: [display_temp: 1]
setup do
expect(MyApp.MockWeatherAPI, :temp, fn
{lat, _long} when lat < -90 or lat > 90 ->
{:error, "latitude must be in the range of -90 to 90 degrees"}
{_lat, _long} ->
{:ok, 30}
end)
:ok
end
end
describe "display_humidity/1" do
doctest MyApp.HumanizedWeather, only: [display_humidity: 1]
setup do
expect(MyApp.MockWeatherAPI, :humidity, fn {_lat, _long} -> {:ok, 60} end)
:ok
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment