Delx v1.0.1 Delx View Source

An Elixir library to make function delegation testable.

Usage

Let's say you have the following module.

iex> defmodule Greeter.StringGreeter do
...>   def hello(name) do
...>     "Hello, #{name}!"
...>   end
...> end

You can delegate functions calls to another module by importing the Delx module and using the defdel/2 macro. It has the same syntax and options as Elixir's own Kernel.defdelegate/2 macro.

iex> defmodule Greeter do
...>   import Delx

...>   defdel hello(name), to: Greeter.StringGreeter
...> end

iex> DelegatingModule.hello("Tobi")
"Hello, Tobi!"

Testing

One great benefit of Delx is that you can test delegation without invoking the actual implementation of the delegation target, thus eliminating all side effects.

With the Stub Delegator

Delx brings it's own stub delegator.

You can activate it for your test environment by putting the following line in your config/test.exs:

config :delx, :stub, true
# or
config :delx, :delegator, Delx.Delegator.Stub

Then in your tests, you can assert whether delegation took place:

defmodule GreeterTest do
  use ExUnit.Case

  import Delx.TestAssertions

  describe "hello/1" do
    test "delegate to Greeter.StringGreeter" do
      assert_delegate {Greeter, :hello, 1}, to: Greeter.StringGreeter
    end
  end
end

With Mox

If you are using Mox in your application you have another possibility to test delegates.

Add the mock for the Delx.Delegator behavior to your test/test_helper.exs:

Mox.defmock(Delx.Delegator.Mock, for: Delx.Delegator)

Then, in your config/test.exs you have to set the mock as delegator module.

config :delx, :delegator, Delx.Delegator.Mock

Please make sure not to use the :stub option and a :delegator option at the same time as this may lead to unexpected behavior.

Now you are able to expect calls to delegated functions:

defmodule GreeterTest do
  use ExUnit.Case

  import Mox

  setup :verify_on_exit!

  describe "hello/1" do
    test "delegate to Greeter.StringGreeter" do
      expect(
        Delx.Delegator.Mock,
        :apply,
        fn {Greeter, :hello},
           {Greeter.StringGreeter, :hello},
           ["Tobi"] ->
        :ok
      end)

      Greeter.hello("Tobi")
    end
  end
end

Link to this section Summary

Functions

The module that is used to control delegation. Has to implement the Delx.Delegator behavior.

Defines a function that delegates to another module. Has the same API as Kernel.defdelegate/2.

Link to this section Functions

Link to this function

__delegator__() View Source
__delegator__() :: module()

The module that is used to control delegation. Has to implement the Delx.Delegator behavior.

Link to this macro

defdel(funs, opts) View Source (macro)

Defines a function that delegates to another module. Has the same API as Kernel.defdelegate/2.