Skip to content

Commit

Permalink
Added with-redefs macro and test
Browse files Browse the repository at this point in the history
  • Loading branch information
jaidetree authored and niwinz committed Feb 23, 2022
1 parent eb4b102 commit e7b4c2c
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/promesa/core.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
(:refer-clojure :exclude [delay spread promise
await map mapcat run!
future let loop recur
-> ->> as->])
-> ->> as-> with-redefs])
(:require
[promesa.protocols :as pt]
[clojure.core :as c]
Expand Down Expand Up @@ -535,3 +535,23 @@
~(if (empty? forms)
name
(last forms))))

(defmacro with-redefs
"Like clojure.core/with-redefs, but it will handle promises in
body and wait until they resolve or reject before restoring the
bindings. Useful for mocking async APIs."
[bindings & body]
(c/let [names (take-nth 2 bindings)
vals (take-nth 2 (drop 1 bindings))
orig-val-syms (map (comp gensym #(str % "-orig-val__") name) names)
temp-val-syms (map (comp gensym #(str % "-temp-val__") name) names)
binds (map vector names temp-val-syms)
resets (reverse (map vector names orig-val-syms))
bind-value (fn [[k v]] (list 'alter-var-root (list 'var k) (list 'constantly v)))]
`(c/let [~@(interleave orig-val-syms names)
~@(interleave temp-val-syms vals)]
~@(map bind-value binds)
(c/-> (do! ~@body)
(finally
(fn []
~@(map bind-value resets)))))))
10 changes: 10 additions & 0 deletions test/promesa/tests/core_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,13 @@
test #(p/then p1 (fn [res] (t/is (= res 8))))]
#?(:cljs (t/async done (p/do! (test) (done)))
:clj @(test))))

(t/deftest with-redefs-macro
(let [a-fn (fn [] (p/resolved "original"))
a-var :original
p1 (p/with-redefs [a-fn (fn [] (p/resolved "mocked"))
a-var :mocked]
(p/then (a-fn) #(vector % a-var)))
test #(p/then p1 (fn [res] (t/is (= res ["mocked" :mocked]))))]
#?(:cljs (t/async done (p/do! (test) (done)))
:clj @(test))))

0 comments on commit e7b4c2c

Please sign in to comment.