Current section
7 Versions
Jump to
Current section
7 Versions
Compare versions
11
files changed
+143
additions
-122
deletions
| @@ -39,14 +39,14 @@ end | |
| 39 39 | ``` |
| 40 40 | |
| 41 41 | You can delegate functions calls to another module by using the `Delx` module |
| 42 | - and calling the `defdel/2` macro in the module body. It has the same API as |
| 42 | + and calling the `defdelegate/2` macro in the module body. It has the same API as |
| 43 43 | Elixir's own `Kernel.defdelegate/2` macro. |
| 44 44 | |
| 45 45 | ```elixir |
| 46 46 | defmodule Greeter do |
| 47 47 | use Delx, otp_app: :greeter |
| 48 48 | |
| 49 | - defdel hello(name), to: Greeter.StringGreeter |
| 49 | + defdelegate hello(name), to: Greeter.StringGreeter |
| 50 50 | end |
| 51 51 | |
| 52 52 | Greeter.hello("Tobi") |
| @@ -63,11 +63,11 @@ effects. | |
| 63 63 | |
| 64 64 | Delx brings it's own test assertions. |
| 65 65 | |
| 66 | - All you need to do is to activate delegation stubbing for your test |
| 67 | - environment by putting the following line in your `config/test.exs`: |
| 66 | + All you need to do is to activate delegation mocking for your test environment |
| 67 | + by putting the following line in your `config/test.exs`: |
| 68 68 | |
| 69 69 | ```elixir |
| 70 | - config :greeter, Delx, stub: true |
| 70 | + config :greeter, Delx, mock: true |
| 71 71 | ``` |
| 72 72 | |
| 73 73 | Then in your tests, you can import `Delx.TestAssertions` and use the |
| @@ -87,8 +87,8 @@ defmodule GreeterTest do | |
| 87 87 | end |
| 88 88 | ``` |
| 89 89 | |
| 90 | - Note that once you activate stubbing all delegated functions do not return |
| 91 | - anymore but instead raise the `Delx.StubbedDelegationError`. If you really |
| 90 | + Note that once you activate mocking all delegated functions do not return |
| 91 | + anymore but instead raise the `Delx.MockedDelegationError`. If you really |
| 92 92 | want to call the original implementation, you have to avoid any calls of |
| 93 93 | delegated functions. |
| 94 94 | |
| @@ -101,18 +101,18 @@ Register a mock for the `Delx.Delegator` behavior to your | |
| 101 101 | `test/test_helper.exs` (or wherever you define your mocks): |
| 102 102 | |
| 103 103 | ```elixir |
| 104 | - Mox.defmock(Delx.Delegator.Mock, for: Delx.Delegator) |
| 104 | + Mox.defmock(Greeter.DelegatorMock, for: Delx.Delegator) |
| 105 105 | ``` |
| 106 106 | |
| 107 107 | Then, in your `config/test.exs` you have to set the mock as delegator module |
| 108 108 | for your app. |
| 109 109 | |
| 110 110 | ```elixir |
| 111 | - config :my_app, Delx, delegator: Delx.Delegator.Mock |
| 111 | + config :my_app, Delx, delegator: Greeter.DelegatorMock |
| 112 112 | ``` |
| 113 113 | |
| 114 | - Please make sure not to use the `:stub` option and a `:delegator` option at |
| 115 | - the same time as this may lead to unexpected behavior. |
| 114 | + Please make sure not to use the `:mock` option and a `:delegator` option at the |
| 115 | + same time as this may lead to unexpected behavior. |
| 116 116 | |
| 117 117 | Now you are able to `expect` calls to delegated functions: |
| 118 118 | |
| @@ -127,7 +127,7 @@ defmodule GreeterTest do | |
| 127 127 | describe "hello/1" do |
| 128 128 | test "delegate to Greeter.StringGreeter" do |
| 129 129 | expect( |
| 130 | - Delx.Delegator.Mock, |
| 130 | + Greeter.DelegatorMock, |
| 131 131 | :apply, |
| 132 132 | fn {Greeter, :hello}, |
| 133 133 | {Greeter.StringGreeter, :hello}, |
| @@ -146,4 +146,24 @@ For more information on how to implement your own delegator, refer to the | |
| 146 146 | docs of the `Delx.Delegator` behavior. |
| 147 147 | |
| 148 148 | Note that the configuration is only applied at compile time, so you are unable |
| 149 | - to stub or replace the delegator module at runtime. |
| 149 | + to mock or replace the delegator module at runtime. |
| 150 | + |
| 151 | + ## Migration from v2 to v3 |
| 152 | + |
| 153 | + Note that the function `defdel/2` has been removed in favor of `defdelegate/2` |
| 154 | + to give a better experience with the tooling. Additionally, let's say you want |
| 155 | + to migrate away from Delx you can simply un`use` Delx to fall back to the |
| 156 | + default `Kernel.defdelegate/2` and your code will still work. |
| 157 | + |
| 158 | + The config option to enable testing mode has changed from `stub` to `mock`. If |
| 159 | + you got the following line in your config: |
| 160 | + |
| 161 | + ```elixir |
| 162 | + config :greeter, Delx, stub: true |
| 163 | + ``` |
| 164 | + |
| 165 | + Please change it to: |
| 166 | + |
| 167 | + ```elixir |
| 168 | + config :greeter, Delx, mock: true |
| 169 | + ``` |
| @@ -5,9 +5,9 @@ | |
| 5 5 | {<<"elixir">>,<<"~> 1.8">>}. |
| 6 6 | {<<"files">>, |
| 7 7 | [<<"lib">>,<<"lib/delx">>,<<"lib/delx/delegator.ex">>, |
| 8 | - <<"lib/delx/defdel.ex">>,<<"lib/delx/stubbed_delegation_error.ex">>, |
| 9 | - <<"lib/delx/delegator">>,<<"lib/delx/delegator/stub.ex">>, |
| 10 | - <<"lib/delx/delegator/common.ex">>,<<"lib/delx/test_assertions.ex">>, |
| 8 | + <<"lib/delx/mocked_delegation_error.ex">>,<<"lib/delx/delegator">>, |
| 9 | + <<"lib/delx/delegator/mock.ex">>,<<"lib/delx/delegator/common.ex">>, |
| 10 | + <<"lib/delx/test_assertions.ex">>,<<"lib/delx/defdelegate.ex">>, |
| 11 11 | <<"lib/delx.ex">>,<<".formatter.exs">>,<<"mix.exs">>,<<"README.md">>, |
| 12 12 | <<"LICENSE">>]}. |
| 13 13 | {<<"licenses">>,[<<"MIT">>]}. |
| @@ -15,4 +15,4 @@ | |
| 15 15 | [{<<"GitHub">>,<<"https://github.com/i22-digitalagentur/delx">>}]}. |
| 16 16 | {<<"name">>,<<"delx">>}. |
| 17 17 | {<<"requirements">>,[]}. |
| 18 | - {<<"version">>,<<"2.1.1">>}. |
| 18 | + {<<"version">>,<<"3.0.0">>}. |
| @@ -13,13 +13,13 @@ defmodule Delx do | |
| 13 13 | ...> end |
| 14 14 | |
| 15 15 | You can delegate functions calls to another module by using the `Delx` |
| 16 | - module and calling the `Delx.Defdel.defdel/2` macro in the module body. It has |
| 16 | + module and calling the `defdelegate/2` macro in the module body. It has |
| 17 17 | the same API as Elixir's own `Kernel.defdelegate/2` macro. |
| 18 18 | |
| 19 19 | iex> defmodule Greeter do |
| 20 20 | ...> use Delx, otp_app: :greeter |
| 21 21 | |
| 22 | - ...> defdel hello(name), to: Greeter.StringGreeter |
| 22 | + ...> defdelegate hello(name), to: Greeter.StringGreeter |
| 23 23 | ...> end |
| 24 24 | |
| 25 25 | iex> Greeter.hello("Tobi") |
| @@ -40,10 +40,10 @@ defmodule Delx do | |
| 40 40 | |
| 41 41 | Delx brings it's own test assertions. |
| 42 42 | |
| 43 | - All you need to do is to activate delegation stubbing for your test |
| 43 | + All you need to do is to activate delegation mocking for your test |
| 44 44 | environment by putting the following line in your `config/test.exs`: |
| 45 45 | |
| 46 | - config :greeter, Delx, stub: true |
| 46 | + config :greeter, Delx, mock: true |
| 47 47 | |
| 48 48 | Then in your tests, you can import `Delx.TestAssertions` and use the |
| 49 49 | `Delx.TestAssertions.assert_delegate/2` and |
| @@ -61,8 +61,8 @@ defmodule Delx do | |
| 61 61 | end |
| 62 62 | end |
| 63 63 | |
| 64 | - Note that once you activate stubbing all delegated functions do not return |
| 65 | - anymore but instead raise the `Delx.StubbedDelegationError`. If you really |
| 64 | + Note that once you activate mocking all delegated functions do not return |
| 65 | + anymore but instead raise the `Delx.MockedDelegationError`. If you really |
| 66 66 | want to call the original implementation, you have to avoid any calls of |
| 67 67 | delegated functions. |
| 68 68 | |
| @@ -74,14 +74,14 @@ defmodule Delx do | |
| 74 74 | Register a mock for the `Delx.Delegator` behavior to your |
| 75 75 | `test/test_helper.exs` (or wherever you define your mocks): |
| 76 76 | |
| 77 | - Mox.defmock(Delx.Delegator.Mock, for: Delx.Delegator) |
| 77 | + Mox.defmock(Greeter.DelegatorMock, for: Delx.Delegator) |
| 78 78 | |
| 79 79 | Then, in your `config/test.exs` you have to set the mock as delegator module |
| 80 80 | for your app. |
| 81 81 | |
| 82 | - config :my_app, Delx, delegator: Delx.Delegator.Mock |
| 82 | + config :my_app, Delx, delegator: Greeter.DelegatorMock |
| 83 83 | |
| 84 | - Please make sure not to use the `:stub` option and a `:delegator` option at |
| 84 | + Please make sure not to use the `:mock` option and a `:delegator` option at |
| 85 85 | the same time as this may lead to unexpected behavior. |
| 86 86 | |
| 87 87 | Now you are able to `expect` calls to delegated functions: |
| @@ -96,7 +96,7 @@ defmodule Delx do | |
| 96 96 | describe "hello/1" do |
| 97 97 | test "delegate to Greeter.StringGreeter" do |
| 98 98 | expect( |
| 99 | - Delx.Delegator.Mock, |
| 99 | + Greeter.DelegatorMock, |
| 100 100 | :apply, |
| 101 101 | fn {Greeter, :hello}, |
| 102 102 | {Greeter.StringGreeter, :hello}, |
| @@ -114,7 +114,7 @@ defmodule Delx do | |
| 114 114 | docs of the `Delx.Delegator` behavior. |
| 115 115 | |
| 116 116 | Note that the configuration is only applied at compile time, so you are unable |
| 117 | - to stub or replace the delegator module at runtime. |
| 117 | + to mock or replace the delegator module at runtime. |
| 118 118 | """ |
| 119 119 | |
| 120 120 | defmacro __using__(opts) do |
| @@ -125,15 +125,16 @@ defmodule Delx do | |
| 125 125 | |
| 126 126 | config = Application.get_env(otp_app, Delx, []) |
| 127 127 | |
| 128 | - case Keyword.fetch(config, :stub) do |
| 128 | + case Keyword.fetch(config, :mock) do |
| 129 129 | {:ok, true} -> |
| 130 | - @delegator Delx.Delegator.Stub |
| 130 | + @delegator Delx.Delegator.Mock |
| 131 131 | |
| 132 132 | _ -> |
| 133 133 | @delegator Keyword.get(config, :delegator, Delx.Delegator.Common) |
| 134 134 | end |
| 135 135 | |
| 136 | - import Delx.Defdel |
| 136 | + import Kernel, except: [defdelegate: 2] |
| 137 | + import Delx.Defdelegate |
| 137 138 | end |
| 138 139 | end |
| 139 140 | end |
| @@ -1,46 +0,0 @@ | |
| 1 | - defmodule Delx.Defdel do |
| 2 | - @moduledoc """ |
| 3 | - A module defining a macro to define delegate functions. |
| 4 | - """ |
| 5 | - |
| 6 | - @doc """ |
| 7 | - You can delegate functions calls to another module by using the `Delx` |
| 8 | - module and calling the `defdel/2` macro in the module body. It has |
| 9 | - the same API as Elixir's own `Kernel.defdelegate/2` macro. |
| 10 | - |
| 11 | - ## Example |
| 12 | - |
| 13 | - Before calling `defdel/2`, you need to use `Delx`. |
| 14 | - |
| 15 | - iex> defmodule Greeter do |
| 16 | - ...> use Delx, otp_app: :greeter |
| 17 | - |
| 18 | - ...> defdel hello(name), to: Greeter.StringGreeter, as: :welcome |
| 19 | - ...> end |
| 20 | - """ |
| 21 | - defmacro defdel(funs, opts) do |
| 22 | - funs = Macro.escape(funs, unquote: true) |
| 23 | - |
| 24 | - quote bind_quoted: [funs: funs, opts: opts] do |
| 25 | - target = |
| 26 | - opts[:to] || raise ArgumentError, "expected to: to be given as argument" |
| 27 | - |
| 28 | - for fun <- List.wrap(funs) do |
| 29 | - {name, args, as, as_args} = Kernel.Utils.defdelegate(fun, opts) |
| 30 | - |
| 31 | - # Dialyzer may possibly complain about "No local return". So we tell him |
| 32 | - # to stop as we're only delegating here. |
| 33 | - @dialyzer {:nowarn_function, [{name, length(as_args)}]} |
| 34 | - |
| 35 | - @doc delegate_to: {target, as, length(as_args)} |
| 36 | - def unquote(name)(unquote_splicing(args)) do |
| 37 | - @delegator.apply( |
| 38 | - {unquote(__MODULE__), unquote(name)}, |
| 39 | - {unquote(target), unquote(as)}, |
| 40 | - unquote(as_args) |
| 41 | - ) |
| 42 | - end |
| 43 | - end |
| 44 | - end |
| 45 | - end |
| 46 | - end |
| @@ -0,0 +1,46 @@ | |
| 1 | + defmodule Delx.Defdelegate do |
| 2 | + @moduledoc """ |
| 3 | + A module defining a macro to define delegate functions. |
| 4 | + """ |
| 5 | + |
| 6 | + @doc """ |
| 7 | + You can delegate functions calls to another module by using the `Delx` |
| 8 | + module and calling the `defdelegate/2` macro in the module body. It has |
| 9 | + the same API as Elixir's own `Kernel.defdelegate/2` macro. |
| 10 | + |
| 11 | + ## Example |
| 12 | + |
| 13 | + Before calling `defdelegate/2`, you need to use `Delx`. |
| 14 | + |
| 15 | + iex> defmodule Greeter do |
| 16 | + ...> use Delx, otp_app: :greeter |
| 17 | + |
| 18 | + ...> defdelegate hello(name), to: Greeter.StringGreeter, as: :welcome |
| 19 | + ...> end |
| 20 | + """ |
| 21 | + defmacro defdelegate(funs, opts) do |
| 22 | + funs = Macro.escape(funs, unquote: true) |
| 23 | + |
| 24 | + quote bind_quoted: [funs: funs, opts: opts] do |
| 25 | + target = |
| 26 | + opts[:to] || raise ArgumentError, "expected to: to be given as argument" |
| 27 | + |
| 28 | + for fun <- List.wrap(funs) do |
| 29 | + {name, args, as, as_args} = Kernel.Utils.defdelegate(fun, opts) |
| 30 | + |
| 31 | + # Dialyzer may possibly complain about "No local return". So we tell him |
| 32 | + # to stop as we're only delegating here. |
| 33 | + @dialyzer {:nowarn_function, [{name, length(as_args)}]} |
| 34 | + |
| 35 | + @doc delegate_to: {target, as, length(as_args)} |
| 36 | + def unquote(name)(unquote_splicing(args)) do |
| 37 | + @delegator.apply( |
| 38 | + {unquote(__MODULE__), unquote(name)}, |
| 39 | + {unquote(target), unquote(as)}, |
| 40 | + unquote(as_args) |
| 41 | + ) |
| 42 | + end |
| 43 | + end |
| 44 | + end |
| 45 | + end |
| 46 | + end |
Loading more files…