In Clojure, how to unit test an async Pedestal interceptor?

379 views Asked by At

I have an async Pedestal interceptor I want to test:

(def my-interceptor
  (io.pedestal.interceptor/interceptor
    {:name  :my-interceptor
     :enter (fn [context]
              (as/go
                (do
                  (Thread/sleep 1000)
                  (assoc context :answer 42))))}))

I first tried a naïve test:

(deftest my-test
  (is (= 42
         (:answer (io.pedestal.interceptor.chain/execute {} [my-interceptor])))))

This doesn’t work because chain/execute returns nil when it has async interceptors. I tried another solution adding the test in an interceptor just after the tested one:

(deftest my-test
  (io.pedestal.interceptor.chain/execute
    {}
    [my-interceptor
     (io.pedestal.interceptor/interceptor
       {:name  :test
        :enter (fn [context]
                 (is (= 41 (:answer context))) ; should fail
                 context)})]))

However this doesn’t work because the test terminates before the test is executed, and thus succeeds… even if the test fails a second after:

Ran 1 test containing 0 assertions.
No failures.

FAIL in (my-test) (somefile_test.clj:49)
expected: (= 41 (:answer context))
  actual: (not (= 41 42))

In practice my tests suite (using Kaocha) fails because there’s a deftest with no assertion in it.

Given that chain/execute returns nil and not a chan, I can’t wrap it in a as/<!! to block until it terminates.

At this point I’m stuck. Is there anything I can do to test that kind of interceptors?

1

There are 1 answers

0
Jochen Bedersdorfer On BEST ANSWER

How about this approach?

(require '[clojure.test :as test])
(require '[clojure.core.async :as async)

(test/deftest async-test []
 (let [c (async/chan)]
      (future (println "Running mah interceptors") (async/>!! c :done))
      (test/is (= :done (async/<!! c)))
      (async/close! c)))

That runs the actual interceptor code in a separate thread. Test code just needs to post something to the c when it is done.