Current section

Files

Jump to
rewire lib rewire.ex
Raw

lib/rewire.ex

defmodule Rewire do
@moduledoc """
Rewire is a libary for replacing hard-wired dependencies of the module your unit testing.
This allows you to keep your production code free of any unit testing-specific concerns.
## Example
```elixir
defmodule Conversation do
def start(), do: English.greet() # the dependency is hard-wired
end
```
You can rewire the dependency with a mock, using `mox` for example:
```elixir
defmodule MyTest do
use ExUnit.Case
use Rewire
import Mox
rewire Conversation, English: Mock # acts as an alias to the rewired module
test "greet" do
stub(Mock, :greet, fn -> "bonjour" end)
assert Conversation.start() == "bonjour" # this uses Mock now!
end
end
```
```elixir
defmodule MyTest do
use ExUnit.Case
use Rewire
import Mox
rewire Conversation, English: Mock # acts as an alias to the rewired module
test "greet" do
stub(Mock, :greet, fn -> "bonjour" end)
assert Conversation.start() == "bonjour" # this uses Mock now!
end
end
```
Alternatively, you can also rewire a module on a test-by-test basis:
```elixir
defmodule MyTest do
use ExUnit.Case
use Rewire
import Mox
test "greet" do
rewire Conversation, English: Mock do # within the block it is rewired
stub(Mock, :greet, fn -> "bonjour" end)
assert Conversation.start() == "bonjour" # this uses Mock now!
end
end
end
```
You can also give the alias a different name using `as`:
```elixir
rewire Conversation, English: Mock, as: SmallTalk
```
"""
defmacro __using__(_) do
quote do
# Needed for importing the `rewire` macro.
import Rewire
end
end
@doc """
Macro that allows to rewire (and alias) a module.
```elixir
use Rewire
rewire App.ModuleToRewire, ModuleDep: Mock
# `ModuleToRewire` will use `Mock` now
end
```
## Options
`opts` is a keyword list:
* `as` - give the rewired module a different name
* any other item, like `ModuleDep: Mock`, will be interpreted as a mapping from one module to another
"""
defmacro rewire(rewire_expr, opts) do
%{aliases: aliases} = __CALLER__
Rewire.Alias.rewire_alias(rewire_expr, opts, aliases)
end
@doc """
Macro that allows to rewire a module within a block.
```elixir
use Rewire
rewire App.ModuleToRewire, ModuleDep: Mock do
# `ModuleToRewire` will use `Mock` now
end
```
See `rewire/2` for a description of options.
"""
defmacro rewire(rewire_expr, opts, do: block) do
%{aliases: aliases} = __CALLER__
Rewire.Block.rewire_block(rewire_expr, opts, aliases, block)
end
end