Hello,
I just published version 1.1 of definject
. It aims to make dependency injection unobtrusive.
import Definject
definject send_welcome_email(user_id) do
%{email: email} = Repo.get(User, user_id)
welcome_email(to: email)
|> Mailer.send()
end
is expanded into (simplified for understanding)
def send_welcome_email(user_id, deps \\ %{}) do
%{email: email} = Map.get(deps, &Repo.get/2, &Repo.get/2).(User, user_id)
welcome_email(to: email)
|> Map.get(deps, &Mailer.send/1, &Mailer.send/1).()
end
Then, you can inject mock functions and modules in tests.
test "send_welcome_email" do
Accounts.send_welcome_email(100, %{
Repo => MockRepo,
&Mailer.send/1 => fn %Email{to: "user100@gmail.com", subject: "Welcome"} ->
Process.send(self(), :email_sent)
end
})
assert_receive :email_sent
end
definject
does not require you to modify function arguments or body. Instead, you just need to replace def
with definject
. It also allows injecting different mocks to each function. It also does not limit using :async
option as mocks are contained in each test function.
You can find definject here:
Thanks!