srnvs
srnvs

Reputation: 1077

Mocking existing methods in Clojure

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.

Upvotes: 3

Views: 1488

Answers (2)

Ming
Ming

Reputation: 4300

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.

Upvotes: 1

Răzvan Petruescu
Răzvan Petruescu

Reputation: 725

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.

Upvotes: 3

Related Questions