Skip to content

Instantly share code, notes, and snippets.

@jprudent
Created September 7, 2021 11:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jprudent/b6ec973daba25dbed3e3cb0d8b40e99d to your computer and use it in GitHub Desktop.
Save jprudent/b6ec973daba25dbed3e3cb0d8b40e99d to your computer and use it in GitHub Desktop.
Mockito but for clojure
(defn mix-behaviours
[& behaviours]
(fn [& args]
(doseq [f (butlast behaviours)]
(apply f args))
(apply (last behaviours) args)))
(defn dyn-type
[implementations]
(let [instance (reify)
t (type instance)]
(doseq [[protocol implem] implementations]
(extend t protocol implem))
t))
(defn new-dyn-type
[implementations]
(clojure.lang.Reflector/invokeConstructor
(dyn-type implementations)
(into-array [])))
(defn mk-mock
[mock-defs]
(new-dyn-type (reduce-kv (fn [acc protocol behaviours]
(assoc acc protocol (apply merge-with mix-behaviours
behaviours)))
{}
mock-defs)))
(defprotocol A
(do-a [this arg]))
(defprotocol B
(do-b [this arg]))
(defn generic-capture
[capture]
(fn [& args] (swap! capture conj args)))
(deftest mocking
(let [capture (atom [])
mock (mk-mock {A [{:do-a (generic-capture capture)}
{:do-a (constantly "done a")}]
B [{:do-b #(println %2)}
{:do-b (constantly "done b")}]})]
(is (= "done a" (do-a mock :arga1)))
(is (= [[mock :arga1]] @capture))
(is (= "done b" (do-b mock :argb)))
(is (= [[mock :arga1]] @capture) "didn't change")
(is (= "done a" (do-a mock :arga2)))
(is (= [[mock :arga1] [mock :arga2]] @capture))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment