diff --git a/src/Mocking.jl b/src/Mocking.jl index d20617d..849d74b 100644 --- a/src/Mocking.jl +++ b/src/Mocking.jl @@ -2,7 +2,7 @@ __precompile__(true) module Mocking -import Compat: uninitialized, @info, @warn +import Compat: uninitialized, @info, @warn, invokelatest if VERSION < v"0.7.0-DEV.3455" hasmethod(f, t) = Base.method_exists(f, t) @@ -217,7 +217,8 @@ macro mock(expr) func = expr.args[1] func_name = QuoteNode(func) - args = expr.args[2:end] + args = filter(x -> !Mocking.iskwarg(x), expr.args[2:end]) + kwargs = extract_kwargs(expr) env_var = gensym("env") args_var = gensym("args") @@ -231,9 +232,9 @@ macro mock(expr) local $env_var = Mocking.get_active_env() local $args_var = tuple($(args...)) if Mocking.ismocked($env_var, $func_name, $args_var) - Base.invokelatest($env_var.mod.$func, $args_var...) + Mocking.invokelatest($env_var.mod.$func, $args_var...; $(kwargs...)) else - $func($args_var...) + $func($args_var...; $(kwargs...)) end end diff --git a/src/expr.jl b/src/expr.jl index 1011aef..959702c 100644 --- a/src/expr.jl +++ b/src/expr.jl @@ -163,3 +163,27 @@ function rewrite_do(expr::Expr) call, body = expr.args Expr(:call, call.args[1], body, call.args[2:end]...) end + +iskwarg(x::Any) = isa(x, Expr) && (x.head === :parameters || x.head === :kw) + +""" + extract_kwargs(expr::Expr) -> Vector{Expr} + +Extract the :parameters and :kw value into an array of :kw expressions +we don't evaluate any expressions for values yet though. +""" +function extract_kwargs(expr::Expr) + kwargs = Expr[] + for x in expr.args[2:end] + if Mocking.iskwarg(x) + if x.head === :parameters + for kw in x.args + push!(kwargs, kw) + end + else + push!(kwargs, x) + end + end + end + return kwargs +end diff --git a/test/optional.jl b/test/optional.jl index e2ed810..105e375 100644 --- a/test/optional.jl +++ b/test/optional.jl @@ -19,6 +19,9 @@ end patch = @patch hourvalue(; hour::Hour=Hour(21)) = 2 * Dates.value(hour) apply(patch) do @test (@mock hourvalue()) == 42 - # @test (@mock hourvalue(hour=Hour(4))) == 8 # TODO + + # Test @mock calls with keyword arguments + @test (@mock hourvalue(hour=Hour(4))) == 8 #:kw + @test (@mock hourvalue(; hour=Hour(4))) == 8 #:parameters end end