3

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.

srnvs
  • 997
  • 2
  • 10
  • 22

2 Answers2

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
  • 1
    This 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