I am trying to use with-redefs
and reify
to mock methods in clojure. I do not have a clue on where to get started with those. Can anyone please give me an example of mocking a method? The documentation on the internet is of no help for me as I am totally confused with it at this point of time.
Asked
Active
Viewed 1,416 times
3

srnvs
- 997
- 2
- 10
- 22
-
3are you looking to mock the methods of a class, or mock a clojure function (that was defined with def or defn) – Arthur Ulfeldt Feb 12 '14 at 21:33
-
@Arthur Ulfeldt : I am looking to mock both – srnvs Feb 13 '14 at 15:12
-
1You may find useful https://github.com/asyntactic/dynamic-reify and this basic example for functions and vars https://gist.github.com/jaimeagudo/8980813 – Jaime Agudo Feb 13 '14 at 18:24
2 Answers
3
The book "The Joy of Clojure (Manning)" might be a good starting point, section '13.2 Testing' has some information with regards to (among others) the technique you mentioned - using the with-redefs
macro.

Răzvan Petruescu
- 685
- 1
- 8
- 16
-
1This is for the 1st edition of the book. If you are using the 2nd Edition of "The Joy of Clojure", this has moved to section 17.2 – sdaas Apr 10 '17 at 03:41
1
Let's say you want to spy/mock/stub a function bar
and test how many times it got called in function foo
. A simple example could be:
(defn bar [] ...)
(defn foo []
(bar)
(bar)
(bar))
(deftest
(let [args (atom [])]
(with-redefs [bar (fn [x] (swap! args conj x))]
(foo)
(is (= (count @args) 3)))))
Well, I agree the code above is a bit tedious. You can try out the following macro: (I put invoke history into meta data)
(defmacro with-mock [vr & body]
`(with-redefs [~vr (with-meta
(fn [& ~'args] (swap! (-> ~vr meta :args) conj ~'args))
{:args (atom [])})]
(do ~@body)))
usage:
(with-mock bar
(foo)
(is (= (-> bar meta :args deref count)
3)))
With a little utilities functions, the macro above could become a powerful tool. The expressiveness of Clojure is so great.

Ming
- 4,110
- 1
- 29
- 33