with-redefs

macrosince v0.0-1806 clojure.core/with-redefsEdit
(with-redefs bindings & body)

Source docstring:
binding => var-symbol temp-value-expr

Temporarily redefines vars while executing the body.  The
temp-value-exprs will be evaluated and each resulting value will
replace in parallel the root value of its var.  After the body is
executed, the root values of all the vars will be set back to their
old values. Useful for mocking out functions during testing.

Note that under advanced compilation vars are statically resolved,
preventing with-redef usage.  If var redefinition is desired in a production
setting then the var to be redefined must be declared ^:dynamic.
Source code @ clojurescript:src/main/clojure/cljs/core.cljc
(core/defmacro with-redefs
  [bindings & body]
  (core/let [names (take-nth 2 bindings)
             vals (take-nth 2 (drop 1 bindings))
             orig-val-syms (map (comp gensym #(core/str % "-orig-val__") name) names)
             temp-val-syms (map (comp gensym #(core/str % "-temp-val__") name) names)
             binds (map core/vector names temp-val-syms)
             resets (reverse (map core/vector names orig-val-syms))
             bind-value (core/fn [[k v]] (core/list 'set! k v))]
    `(let [~@(interleave orig-val-syms names)
           ~@(interleave temp-val-syms vals)]
       ~@(map bind-value binds)
       (try
         ~@body
         (finally
           ~@(map bind-value resets))))))