git clone git@github.com:am-kantox/bex
cd bex
mix deps.get
mix compile
This is the only file in the sources having Process.send_after/4
calls.
cat test/support/source.ex
defmodule Bex.Test.Process do
@moduledoc false
alias Elixir.Process, as: P1
alias Process, as: P2
alias Task.Supervisor
def schedule_without_as do
Supervisor.start_link([])
end
def schedule(interval) do
Process.send_after(self(), :schedule, interval, [])
end
def schedule_with_fq_alias do
P1.send_after(self(), :schedule, 1_000, [])
end
def schedule_with_alias do
P2.send_after(self(), :schedule, 1_000, [])
end
end
Task invocation with all the defaults.
mix bex.generate --function Process.send_after/4
* creating lib/bex/process.ex
✓ Process has been created in lib/bex/process.ex
✓ Suggested change: test/support/source.ex:15 in Bex.Test.Process.schedule(interval)
- Process.send_after(self(), :schedule, interval, [])
+ Bex.Behaviours.Process.send_after(self(), :schedule, interval, [], __ENV__)
✓ Suggested change: test/support/source.ex:19 in Bex.Test.Process.schedule_with_fq_alias()
- P1.send_after(self(), :schedule, 1_000, [])
+ Bex.Behaviours.Process.send_after(self(), :schedule, 1_000, [], __ENV__)
✓ Suggested change: test/support/source.ex:23 in Bex.Test.Process.schedule_with_alias()
- P2.send_after(self(), :schedule, 1_000, [])
+ Bex.Behaviours.Process.send_after(self(), :schedule, 1_000, [], __ENV__)
Apply changes to ‹test/support/source.ex›? [Yn]
✓ File test/support/source.ex amended successfully
* creating test/bex/process_test.exs
✓ Bex.Behaviours.Process.Mox.Test has been created in test/bex/process_test.exs
Patch ‹config/config.exs›? [Yn]
✓ config/config.exs has been altered
git diff
diff --git a/test/support/source.ex b/test/support/source.ex
index 620aab9..c3d0829 100644
--- a/test/support/source.ex
+++ b/test/support/source.ex
@@ -12,14 +12,14 @@ defmodule Bex.Test.Process do
end
def schedule(interval) do
- Process.send_after(self(), :schedule, interval, [])
+ Bex.Behaviours.Process.send_after(self(), :schedule, interval, [], __ENV__)
end
def schedule_with_fq_alias do
- P1.send_after(self(), :schedule, 1_000, [])
+ Bex.Behaviours.Process.send_after(self(), :schedule, 1_000, [], __ENV__)
end
def schedule_with_alias do
- P2.send_after(self(), :schedule, 1_000, [])
+ Bex.Behaviours.Process.send_after(self(), :schedule, 1_000, [], __ENV__)
end
-end
+end
The above is the only diff. Generated:
# lib/bex/process.ex
defmodule Bex.Behaviours.Process do
@moduledoc false
_ = """
Behaviour wrapping Process
"""
@doc false
@callback send_after(arg_1 :: any(), arg_2 :: any(), arg_3 :: any(), arg_4 :: any()) :: any()
# default implementation
@actual_impls Application.compile_env(:bex, :impls, %{})
@actual_impl Map.get(@actual_impls, Process, Bex.Behaviours.Impls.Process)
@doc false
defdelegate send_after(arg_1, arg_2, arg_3, arg_4), to: @actual_impl
@doc false
def send_after(arg_1, arg_2, arg_3, arg_4, %Macro.Env{} = env) do
event_prefix = Bex.telemetry_event_base(env)
:telemetry.execute(
event_prefix ++ [:start],
Bex.telemetry_measurements_base(%{}),
%{
arg_1: arg_1,
arg_2: arg_2,
arg_3: arg_3,
arg_4: arg_4
}
)
result =
send_after(arg_1, arg_2, arg_3, arg_4)
:telemetry.execute(
event_prefix ++ [:stop],
Bex.telemetry_measurements_base(%{}),
%{result: result}
)
result
end
end
defmodule Bex.Behaviours.Impls.Process do
@moduledoc false
_ = """
Default implementation for the behaviour wrapping Process
"""
@behaviour Bex.Behaviours.Process
@impl Bex.Behaviours.Process
def send_after(arg_1, arg_2, arg_3, arg_4) do
Process.send_after(arg_1, arg_2, arg_3, arg_4)
end
end
case {Code.ensure_compiled(Mox), Mix.env()} do
{{:module, Mox}, :test} ->
Bex.Behaviours.Process
|> Module.concat(Mox)
|> Mox.defmock(for: Bex.Behaviours.Process)
{_, :test} ->
IO.warn("Please add `mox` to deps in `test` env")
_ ->
:ok
end
# test/bex/process_test.ex
defmodule Bex.Behaviours.Process.Mox.Test do
use ExUnit.Case, async: true
import Mox
test "Bex.Test.Process.schedule/1" do
test_process = self()
Bex.Behaviours.Process.Mox
|> expect(:send_after, 1, fn _arg_1, _arg_2, _arg_3, _arg_4 ->
send(test_process, {:schedule, 4})
end)
Bex.Test.Process.schedule(nil)
assert_receive({:schedule, 4})
end
test "Bex.Test.Process.schedule_with_fq_alias/0" do
test_process = self()
Bex.Behaviours.Process.Mox
|> expect(:send_after, 1, fn _arg_1, _arg_2, _arg_3, _arg_4 ->
send(test_process, {:schedule_with_fq_alias, 4})
end)
Bex.Test.Process.schedule_with_fq_alias()
assert_receive({:schedule_with_fq_alias, 4})
end
test "Bex.Test.Process.schedule_with_alias/0" do
test_process = self()
Bex.Behaviours.Process.Mox
|> expect(:send_after, 1, fn _arg_1, _arg_2, _arg_3, _arg_4 ->
send(test_process, {:schedule_with_alias, 4})
end)
Bex.Test.Process.schedule_with_alias()
assert_receive({:schedule_with_alias, 4})
end
end
Patched/generated:
# config/config.exs
import Config
config :bex,
:impls,
(if Mix.env() == :test do
%{Process => Bex.Behaviours.Process.Mox}
else
%{Process => Bex.Behaviours.Impls.Process}
end)