Skip to content

Instantly share code, notes, and snippets.

@mwmitchell
Created April 6, 2013 12:26
Show Gist options
  • Save mwmitchell/5325944 to your computer and use it in GitHub Desktop.
Save mwmitchell/5325944 to your computer and use it in GitHub Desktop.
(defn redefine [binding-map func]
(let [old-vals (zipmap (keys binding-map)
(map #(.getRawRoot ^clojure.lang.Var %) (keys binding-map)))
hits (zipmap (keys binding-map)
(map (fn [_] (atom 0)) (keys binding-map)))
wrappers (zipmap (keys binding-map)
(map #(fn [& args]
(let [[f limit] (get binding-map %)
h (get hits %)
old (get old-vals %)]
(swap! h inc)
(when (and limit (> @h limit))
(throw (Exception. (format
"You said %s should be called %s times but it was called %s" % limit @h))))
(apply f old args)))
(keys binding-map)))
root-bind (fn [m]
(doseq [[a-var a-val] m]
(.bindRoot ^clojure.lang.Var a-var a-val)))]
(try
(root-bind wrappers)
(let [return (func)]
(doall (for [[k v] hits
:let [x (last (get binding-map k))]
:when (> x @v)]
(throw (Exception. (format "You said %s would be called %s times but it was called %s" k x @v)))))
return)
(finally
(root-bind old-vals)))))
(defn add [& nums]
(apply + nums))
(defn plus2 [& nums]
(add (apply add nums) 2))
(require '[clojure.test :refer :all])
(redefine {(var add) [(fn [f & args] (apply f args)) 2]}
(fn []
(is (= (plus2 100) 102))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment