wedesoft
wedesoft

Reputation: 2989

Assert call to mock happened in Clojure test

In my unit tests in Clojure I am trying to assert that a call has happened. The following code checks the call arguments but it doesn't check whether the call actually happened.

(require '[clojure.test :refer :all])
(defn g [x] (* x x))
(defn f [x] (inc (g x)))
(deftest f-g-test
  (testing "f(x) calls g(x)"
    (with-redefs [g (fn [x] (is (= x 3)) 9)]
      (is (= (f 3) 10)))))
(run-tests)

Is there a compact way to assert that the call has happened?

Upvotes: 1

Views: 450

Answers (2)

wedesoft
wedesoft

Reputation: 2989

In the meantime I found out that Midje has a facility for mocking which checks that the call(s) actually happened:

(use 'midje.repl)

(defn g [x] (* x x))
(defn f [x] (inc (g x)))

(fact "f(x) calls g(x)"
  (f 3) => 10
  (provided
    (g 3) => 9))

Upvotes: 0

Alan Thompson
Alan Thompson

Reputation: 29958

You need some piece of state that can remember if function g was called. It could be an atom, or a (possibly dynamic) var:

(deftest f-g-test
  (testing "f(x) calls g(x)"
    (let [called? (atom false)]
      (with-redefs [g (fn [x]
                        (reset! called? true)
                        (is (= x 3)) 9)]
        (is (= (f 3) 10))
        (is (= true @called?))))))

The comparison to true guards against the mistake of forgetting the @ sign, compared to:

(is called?)  

which always passes, even if the function is never called.

Upvotes: 2

Related Questions