definject alternatives and similar packages
Based on the "Testing" category.
Alternatively, view definject alternatives based on common mentions on social networks and blogs.
-
hound
Elixir library for writing integration tests and browser automation -
proper
PropEr: a QuickCheck-inspired property-based testing tool for Erlang -
bypass
Bypass provides a quick way to create a custom plug that can be put in place instead of an actual HTTP server to return prebaked responses to client requests. -
StreamData
Data generation and property-based testing for Elixir. ๐ฎ -
ExVCR
HTTP request/response recording library for elixir, inspired by VCR. -
amrita
A polite, well mannered and thoroughly upstanding testing framework for Elixir -
power_assert
Power Assert in Elixir. Shows evaluation results each expression. -
FakerElixir
[unmaintained] FakerElixir generates fake data for you. -
shouldi
Elixir testing libraries with nested contexts, superior readability, and ease of use -
katt
KATT (Klarna API Testing Tool) is an HTTP-based API testing tool for Erlang. -
FakeServer
FakeServer integrates with ExUnit to make external APIs testing simpler -
Stubr
Stubr is a set of functions helping people to create stubs and spies in Elixir. -
mix_test_interactive
Interactive watch mode for Elixir's mix test. https://hexdocs.pm/mix_test_interactive/ -
mecks_unit
A simple Elixir package to elegantly mock module functions within (asynchronous) ExUnit tests using Erlang's :meck library -
test_selector
Elixir library to help selecting the right elements in your tests. -
factory_girl_elixir
Minimal implementation of Ruby's factory_girl in Elixir. -
toxiproxy_ex
ToxiproxyEx is an Elixir API client for the resilience testing tool Toxiproxy. -
ex_parameterized
This library support parameterized test with test_with_params macro. -
mix_erlang_tasks
Common tasks for Erlang projects that use Mix -
cobertura_cover
Output test coverage information in Cobertura-compatible format -
ex_unit_fixtures
A library for defining modular dependencies (fixtures) for ExUnit tests.
Learn any GitHub repo in 59 seconds
Do you think we are missing an alternative of definject or a related project?
Popular Comparisons
README
Unobtrusive Dependency Injector for Elixir
Why?
Let's say we want to test following function.
def send_welcome_email(user_id) do
%{email: email} = Repo.get(User, user_id)
welcome_email(to: email)
|> Mailer.send()
end
Here's one possible solution to replace Repo.get/2
and Mailer.send/1
with mocks:
def send_welcome_email(user_id, repo \\ Repo, mailer \\ Mailer) do
%{email: email} = repo.get(User, user_id)
welcome_email(to: email)
|> mailer.send()
end
First, I believe that this approach is too obtrusive as it requires modifying the function body to make it testable. Second, with Mailer
replaced with mailer
, the compiler no longer check the existence of Mailer.send/1
.
definject
does not require you to modify function arguments or body. It allows injecting different mocks to each function. It also does not limit using :async
option as mocks are contained in each test function.
Installation
The package can be installed by adding definject
to your list of dependencies
in mix.exs
:
def deps do
[{:definject, "~> 1.2"}]
end
By default, definject
is replaced with def
in all but the test environment. Add the below configuration to enable in other environments.
config :definject, :enable, true
To format definject
like def
, add following to your .formatter.exs
locals_without_parens: [definject: 1, definject: 2]
Documentation
API documentation is available at https://hexdocs.pm/definject
Usage
use Definject
use Definject
transforms def
to accept a extra argument deps
where dependent functions and modules can be injected.
use Definject
def send_welcome_email(user_id) do
%{email: email} = Repo.get(User, user_id)
welcome_email(to: email)
|> Mailer.send()
end
is expanded into
def send_welcome_email(user_id, deps \\ %{}) do
%{email: email} =
Map.get(deps, &Repo.get/2,
:erlang.make_fun(Map.get(deps, Repo, Repo), :get, 2)
).(User, user_id)
welcome_email(to: email)
|> Map.get(deps, &Mailer.send/1,
:erlang.make_fun(Map.get(deps, Mailer, Mailer), :send, 1)
).()
end
Note that local function calls like welcome_email(to: email)
are not expanded unless it is prepended with __MODULE__
.
Now, 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: "[email protected]", subject: "Welcome"} ->
Process.send(self(), :email_sent)
end
})
assert_receive :email_sent
end
Function calls raise if the deps
includes redundant functions or modules.
You can disable this by adding strict: false
option.
test "send_welcome_email with strict: false" do
Accounts.send_welcome_email(100, %{
&Repo.get/2 => fn User, 100 -> %User{email: "[email protected]"} end,
&Repo.all/1 => fn _ -> [%User{email: "use[email protected]"}] end, # Unused
strict: false
})
end
mock
If you don't need pattern matching in mock function, mock/1
can be used to reduce boilerplates.
import Definject
test "send_welcome_email with mock/1" do
Accounts.send_welcome_email(
100,
mock(%{
Repo => MockRepo,
&Mailer.send/1 => Process.send(self(), :email_sent)
})
)
assert_receive :email_sent
end
Note that Process.send(self(), :email_sent)
is surrounded by fn _ -> end
when expanded.
import Definject
import Definject
instead of use Definject
if you want to manually select functions to inject.
import Definject
definject send_welcome_email(user_id) do
%{email: email} = Repo.get(User, user_id)
welcome_email(to: email)
|> Mailer.send()
end
License
This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details
*Note that all licence references and agreements mentioned in the definject README section above
are relevant to that project's source code only.