...
/Finer Control over Dependency Injection
Finer Control over Dependency Injection
Learn how Dependency Injection can be fine-tuned.
We'll cover the following...
An alternative to injecting a whole function is to pass in a single value. An example we might see in code is when the outside dependency is the system time. If our code under test needs to do something with system time, it’s very difficult for our tests to assert a known response or value unless we can control system time. While controlling our code’s concept of system time is easy in some languages, it isn’t in Elixir. That makes this scenario a perfect candidate for injecting a single value.
The following code allows for an injected value, but it defaults to the result of a function call if no parameter is passed:
#file path -> soggy_waffle/lib/soggy_waffle/weather.exdefmodule SoggyWaffle.Weather do@type t :: %__MODULE__{}defstruct [:datetime, :rain?]@spec imminent_rain?([t()], DateTime.t()) :: boolean()def imminent_rain?(weather_data, now \\ DateTime.utc_now()) doEnum.any?(weather_data, fn%__MODULE__{rain?: true} = weather ->in_next_4_hours?(now, weather.datetime)_ ->falseend)enddefp in_next_4_hours?(now, weather_datetime) dofour_hours_from_now =DateTime.add(now, _4_hours_in_seconds = 4 * 60 * 60)DateTime.compare(weather_datetime, now) in [:gt, :eq] andDateTime.compare(weather_datetime, four_hours_from_now) in [:lt, :eq]endend
In the above code, in line 8, we can see that without a value passed in, the result of DateTime.utc_now/0
will be bound to the variable datetime
. Our tests will pass ...