What are the techniques and libraries to do the integration testing in Clojure. Specifically interaction with databases, ring applications, core.async channels, anything which produces a side-effect.
You can use ring-mock for ring applications. An example of creating a mock handler and using it is:
(let [h (-> (POST "/some/url" [] some-resource)
(wrap-defaults api-defaults))]
(let [resp (h (-> (request :post "/some/url")
(header "content-type" "application/json")
(body (generate-string {:foo :bar}))))]
(is (= 303 (:status resp)))
(is (= "" (:body resp)))
(is (= "http://some/place/foo" (get-in resp [:headers "Location"])))))
For d/b interation testing and side-effects, I use with-redefs to stub out the actual side-effecting function and capture and test the arguments to it are as expected. I'm not sure if this is idiomatic, but it's what I've found the easiest, e.g.
(testing "some d/b work"
(let [insert-data (ref {})]
(with-redefs
[d/insert-data<!
(fn [db data] (dosync (alter insert-data assoc :db db)
(alter insert-data assoc :data data)))]
(let [d (your-fn your-args)]
(is (= {:some :expected-result} d))
(is (= {:db {:some :connection-data} :data {:some :expected-data}} @insert-data))))))
You can use atoms here, historically I've had to use refs when I was testing some agents that did write-back work, and atoms didn't work in that scenario.
The main library I use is clojure.test, I only briefly dabbled with property testing using test.check so far. I used Midje for a while, but found clojure.test felt purer, but that was down to taste. Plus if you're venturing into cljs, you may as well stick with one testing framework.
I haven't any experience using core.async, but its own tests look like a good place to start.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With