README.md

# Inject

Inject is a library that lets you write testable Elixir code that can run concurrently in ExUnit.

## Installation

```elixir
def deps do
  [
    {:inject, "~> 0.4.0"}
  ]
end
```

It is recommended to disable inject in prod.exs to avoid any performance penalty for registry lookups.
```
config :inject, disabled: true
```

## Usage

Inject is just a couple of functions.

- `inject/1` aliased as `i/1`. Use this function in your implementation code to flag modules for potential injection.

```elixir
defmodule MyApplication do
  import Inject, only: [i: 1]

  def process do
    {:ok, file} = i(File).open("your-mind.txt", [])
    ...
  end
end
```

- `register/2` `register/3`. Use this function in your tests to register a stubbed implementation for a module.

```elixir
defmodule MyApplicationTest do
  use ExUnit.Case, async: true
  import Inject, only: [register: 2]

  defmodule FileStub do
    def open("your-mind.txt", _opts) do
      {:ok, nil}
    end
  end

  test "use my stub for this test" do
    register(File, FileStub)
    {:ok, nil} = MyApplication.process()
  end
end
```
Defining stubbed modules like this is great, but I like to pair Inject w/ [Double](https://hex.pm/packages/double) for on-the-fly setups.

```elixir
defmodule MyApplicationTest do
  use ExUnit.Case, async: true
  import Inject, only: [register: 2]
  import Double

  test "use my stub for this test" do
    register(File, stub(File, :open, fn(_, _) -> {:ok, nil} end))
    {:ok, nil} = MyApplication.process()
  end
end
```

### Shared Mode
If you want to inject a dependency that will be shared by all processes, you can do so by passing the `shared: true` option.
This can be useful if you have background processing. This is only recommended for tests that do not run async.

```elixir
register(File, FileStub, shared: true)
```

## TODO
- Add `allow/1` for enabling another process to use registrations from the current test.