diff --git a/lib/mox.ex b/lib/mox.ex index a69fa1e..ab184e7 100644 --- a/lib/mox.ex +++ b/lib/mox.ex @@ -523,7 +523,8 @@ defmodule Mox do end for behaviour <- behaviours, - {fun, arity} <- behaviour.behaviour_info(:callbacks) do + {fun, arity} <- behaviour.behaviour_info(:callbacks), + function_exported?(mock, fun, arity) do stub(mock, fun, :erlang.make_fun(module, fun, arity)) end diff --git a/test/mox_test.exs b/test/mox_test.exs index 8b1742a..cb9aa76 100644 --- a/test/mox_test.exs +++ b/test/mox_test.exs @@ -583,6 +583,16 @@ defmodule MoxTest do def exponent(x, y), do: :math.pow(x, y) end + defmodule SciCalcFullImplementation do + @behaviour Calculator + def add(x, y), do: x + y + def mult(x, y), do: x * y + + @behaviour ScientificCalculator + def exponent(x, y), do: :math.pow(x, y) + def sin(x), do: :math.sin(x) + end + test "can override stubs" do in_all_modes(fn -> stub_with(CalcMock, CalcImplementation) @@ -603,6 +613,29 @@ defmodule MoxTest do end) end + test "stubs functions which are optional callbacks" do + in_all_modes(fn -> + stub_with(SciCalcMock, SciCalcFullImplementation) + assert SciCalcMock.add(1, 2) == 3 + assert SciCalcMock.mult(3, 4) == 12 + assert SciCalcMock.exponent(2, 10) == 1024 + assert SciCalcMock.sin(0) == 0.0 + end) + end + + test "skips undefined functions which are optional callbacks" do + in_all_modes(fn -> + stub_with(SciCalcMockWithoutOptional, SciCalcImplementation) + assert SciCalcMockWithoutOptional.add(1, 2) == 3 + assert SciCalcMockWithoutOptional.mult(3, 4) == 12 + assert SciCalcMockWithoutOptional.exponent(2, 10) == 1024 + + assert_raise UndefinedFunctionError, fn -> + SciCalcMockWithoutOptional.sin(1) + end + end) + end + test "Leaves behaviours not implemented by the module un-stubbed" do in_all_modes(fn -> stub_with(SciCalcMock, CalcImplementation) diff --git a/test/support/mocks.ex b/test/support/mocks.ex index 3083342..d855695 100644 --- a/test/support/mocks.ex +++ b/test/support/mocks.ex @@ -1,5 +1,6 @@ Mox.defmock(CalcMock, for: Calculator) Mox.defmock(SciCalcMock, for: [Calculator, ScientificCalculator]) +Mox.defmock(SciCalcMockWithoutOptional, for: [Calculator, ScientificCalculator], skip_optional_callbacks: true) Mox.defmock(MyMockWithoutModuledoc, for: Calculator) Mox.defmock(MyMockWithFalseModuledoc, for: Calculator, moduledoc: false)