I\'m trying to write unit tests when using core.async go macros. Writing the test naively, as follows, appears that the code inside the go blocks doesn\'t get executed.
Tests are executed synchronously, so if you go async the test-runner won't. In Clojure you need to block the test runner via , in ClojureScript you have to return an async test object. This is a generic helper function I use in all my async CLJC tests:
(defn test-async
"Asynchronous test awaiting ch to produce a value or close."
[ch]
#?(:clj
(
Your test using it, CLJC compatible and looking way less "hacky":
(deftest test1
(let [ch (chan)]
(go (>! ch "Hello"))
(test-async
(go (is (= "Hello" (
It is good practice to assert that the test unblocks, especially during test driven development where you want to avoid locking your test runner. Also, locking is a common cause of failure in async programming, so testing against it is highly reasonable.
To do that I wrote a helper similar to your timeout thing:
(defn test-within
"Asserts that ch does not close or produce a value within ms. Returns a
channel from which the value can be taken."
[ms ch]
(go (let [t (timeout ms)
[v ch] (alts! [ch t])]
(is (not= ch t)
(str "Test should have finished within " ms "ms."))
v)))
You can use it to write your test like:
(deftest test1
(let [ch (chan)]
(go (>! ch "Hello"))
(test-async
(test-within 1000
(go (is (= "Hello" (