Skip to content

Commit 6e0ee96

Browse files
committed
fix: call_original must have the module already copied
Very rare case where call_original is called before expectations/stubs are set-up for a module
1 parent ac567d7 commit 6e0ee96

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

lib/mimic.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,14 @@ defmodule Mimic do
414414
arity = length(args)
415415

416416
raise_if_not_exported_function!(module, function_name, arity)
417+
418+
if Mimic.Module.copied?(module) == false do
419+
case Mimic.Server.ensure_copied(module) do
420+
:ok -> :ok
421+
error -> validate_server_response(error, :call_original)
422+
end
423+
end
424+
417425
func = Function.capture(Mimic.Module.original(module), function_name, arity)
418426

419427
Kernel.apply(func, args)

lib/mimic/server.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ defmodule Mimic.Server do
112112
GenServer.call(__MODULE__, {:get_calls, {module, fn_name, arity}, self()})
113113
end
114114

115+
@spec ensure_copied(module) :: :ok | {:error, {:module_not_copied, module}}
116+
def ensure_copied(module) do
117+
GenServer.call(__MODULE__, {:ensure_copied, module}, @long_timeout)
118+
end
119+
115120
def apply(module, fn_name, args) do
116121
arity = Enum.count(args)
117122
original_module = Mimic.Module.original(module)
@@ -575,6 +580,13 @@ defmodule Mimic.Server do
575580
end
576581
end
577582

583+
def handle_call({:ensure_copied, module}, _from, state) do
584+
case ensure_module_copied(module, state) do
585+
{:ok, new_state} -> {:reply, :ok, new_state}
586+
{:error, reason} -> {:reply, {:error, reason}, state}
587+
end
588+
end
589+
578590
defp maybe_typecheck_func(module, fn_name, func) do
579591
case module.__mimic_info__() do
580592
{:ok, %{type_check: true}} ->

test/mimic_test.exs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,24 @@ defmodule Mimic.Test do
10311031
describe "call_original/3" do
10321032
setup :set_mimic_private
10331033

1034+
test "calling call_original on a module that has not been copied yet" do
1035+
module = Mimic.CallOriginalTestModule
1036+
# Calling copy here but Mimic does not actually copy until Mimic is needed
1037+
assert_raise ArgumentError,
1038+
"Module Mimic.CallOriginalTestModule has not been copied. See docs for Mimic.copy/1",
1039+
fn ->
1040+
assert Mimic.call_original(module, :my_function, []) ==
1041+
:original
1042+
end
1043+
1044+
Mimic.copy(module)
1045+
assert Mimic.Module.copied?(module) == false
1046+
assert Mimic.call_original(module, :my_function, []) == :original
1047+
1048+
# call_original should copy the module
1049+
assert Mimic.Module.copied?(module) == true
1050+
end
1051+
10341052
test "calls original function even if it has been is stubbed" do
10351053
stub_with(Calculator, InverseCalculator)
10361054

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
defmodule Mimic.CallOriginalTestModule do
2+
def my_function, do: :original
3+
end

0 commit comments

Comments
 (0)