API
Mocking.activate — FunctionMocking.activate() -> NothingActivates @mock call sites to allow for calling patches instead of the original function. Intended to be called within a packages test/runtests.jl file.
Calling this causes functions which use @mock to become invalidated and re-compiled the next time they are called.
Mocking.activated — FunctionMocking.activated() -> BoolIndicates if Mocking has been activated or not via Mocking.activate.
Mocking.nullify — FunctionMocking.nullify() -> NothingForce any packages loaded after this point to treat the @mock macro as a no-op. Doing so will maximize performance by eliminating any runtime checks taking place at the @mock call sites but will break any tests that require patches to be applied.
Note to ensure that all @mock macros are inoperative be sure to call this function before loading any packages which depend on Mocking.jl.
Mocking.@mock — Macro@mock exprAllows the call site function to be temporarily overloaded via an applied patch.
The @mock macro works as no-op until Mocking.activate has been called. Once Mocking has been activated then alternative methods defined via @patch can be used with apply to call the patched methods from within the apply context.
Examples
julia> f() = @mock time();
julia> p = @patch time() = 0.0; # UNIX epoch
julia> apply(p) do
Dates.unix2datetime(f())
end
1970-01-01T00:00:00Mocking.@patch — Macro@patch exprCreates a patch from a function definition. A patch can be used with apply to temporarily include the patch when performing multiple dispatch on @mocked call sites.
Mocking.apply — Functionapply(body::Function, patches) -> AnyApplies one or more patches during execution of body. Specifically ,any @mock call sites encountered while running body will include the provided patches when performing dispatch.
Multiple-dispatch is used to determine which method to call when utilizing multiple patches. However, patch defined methods always take precedence over the original function methods.
Ensure you have called activate prior to calling apply as otherwise the provided patches will be ignored.
Examples
Applying a patch allows the alternative patch function to be called:
julia> f() = "original";
julia> p = @patch f() = "patched";
julia> apply(p) do
@mock f()
end
"patched"Patches take precedence over the original function even when the original method is more specific:
julia> f(::Int) = "original";
julia> p = @patch f(::Any) = "patched";
julia> apply(p) do
@mock f(1)
end
"patched"However, when the patches do not provide a valid method to call then the original function will be used as a fallback:
julia> f(::Int) = "original";
julia> p = @patch f(::Char) = "patched";
julia> apply(p) do
@mock f(1)
end
"original"Nesting
Nesting multiple apply calls is allowed. When multiple patches are provided for the same method then the innermost patch takes precedence:
julia> f() = "original";
julia> p1 = @patch f() = "p1";
julia> p2 = @patch f() = "p2";
julia> apply(p1) do
apply(p2) do
@mock f()
end
end
"p2"When multiple patches are provided for different methods then multiple-dispatch is used to select the most specific patch:
julia> f(::Int) = "original";
julia> p1 = @patch f(::Integer) = "p1";
julia> p2 = @patch f(::Number) = "p2";
julia> apply(p1) do
apply(p2) do
@mock f(1)
end
end
"p1"