Welcome! Please see the About page for a little more info on how this works.

0 votes
in Test by
edited by

I'm trying to test that one function (foo/my-function-under-test below) handles exceptions the way I want it to. Specifically, the function invokes clj-http.client/get to make an HTTP request, and if the host is unavailable, I want the function under test to retry up to three times. If it gets through three retries and still can't reach the host, I want it to throw my ServiceUnavailable exception.

The code below is not right, but it should express my intent. I know that retries-count isn't a variable. I also know I could use dynamic rebinding to make it act like a variable. But is there an idiomatic functional way of doing this without simulating variables?

(deftest retries
  (let [retry-count 0]
    (with-redefs [clj-http.client/get (fn [url & [req & r]]
                                        retry-count++
                                        (throw (UnknownHostException. "Some message")))]
      (is (thrown? ServiceUnavailable (foo/my-function-under-test)))
      (is (= 3 retry-count)))))

1 Answer

0 votes
by

You could make retry-count an atom and then use swap! to increment it.

(deftest retries
  (let [retry-count (atom 0)]
    (with-redefs [clj-http.client/get (fn [url & [req & r]]
                                        (swap! retry-count inc)
                                        (throw (UnknownHostException. "Some message")))]
      (is (thrown? ServiceUnavailable (foo/my-function-under-test)))
      (is (= 3 @retry-count)))))
...