diff options
author | Chouser <chouser@n01se.net> | 2010-10-29 11:26:46 -0400 |
---|---|---|
committer | Stuart Halloway <stu@thinkrelevance.com> | 2010-11-05 08:41:43 -0700 |
commit | 178d8c42609d899208e745b76b89297c4287c078 (patch) | |
tree | 8b0383e11dd5a28fc0838f83efccf35d7c21cb56 /src | |
parent | e354b01133e7cff8dc0d0eb9e90cde894c12e127 (diff) |
Add with-redefs macro and with-redefs-fn, CLJ-665
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/clj/clojure/core.clj | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 42ca9449..4cdf794d 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -6193,3 +6193,38 @@ [fdecl] (if-let [bad-args (seq (remove #(vector? %) (map first fdecl)))] (throw (IllegalArgumentException. (str "Parameter declaration " (first bad-args) " should be a vector"))))) + +(defn with-redefs-fn + "Temporarily redefines Vars during a call to func. Each val of + binding-map will replace the root value of its key which must be + a Var. After func is called with no args, the root values of all + the Vars will be set back to their old values. These temporary + changes will be visible in all threads. Useful for mocking out + functions during testing." + {:added "1.3"} + [binding-map func] + (let [root-bind (fn [m] + (doseq [[a-var a-val] m] + (.bindRoot ^clojure.lang.Var a-var a-val))) + old-vals (zipmap (keys binding-map) + (map deref (keys binding-map)))] + (try + (root-bind binding-map) + (func) + (finally + (root-bind old-vals))))) + +(defmacro with-redefs + "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. These temporary changes will be visible in all threads. + Useful for mocking out functions during testing." + {:added "1.3"} + [bindings & body] + `(with-redefs-fn ~(zipmap (map #(list `var %) (take-nth 2 bindings)) + (take-nth 2 (next bindings))) + (fn [] ~@body))) |