Clojure: expectations & with-redefs
In general, when I'm writing tests, the pure functions end up as bare expects and the impure functions end up as scenarios. The following contrived namespace keeps a list of users and allows you to get the full name of each user.
(ns user)
(def users (atom #{}))
(defn full-name [{:keys [fname lname]}] (str fname " " lname))
(defn all-names [] (map full-name @users))The tests for this namespace would often look something like the following code:
(ns user-expectations
(:use expectations user))
(expect "John Dory" (full-name {:fname "John" :lname "Dory"}))
(ns user-expectations.scenarios
(:use expectations.scenarios user))
(scenario
(with-redefs [users (atom #{{:fname "Mary", :lname "Dory"} {:fname "John", :lname "Dory"}})]
(expect ["Mary Dory" "John Dory"] (all-names))))
It feels natural to put the with-redefs in a scenario, since scenarios also support (and often make use of) stubbing, localize-state, & freeze-time. However, there's really no reason that you need to use a scenario if you're simply looking to redef a var.
The following test provides the same level of functionality verification, without needing to use expectations.scenarios:
(ns user-expectations
(:use expectations user))
(expect "John Dory" (full-name {:fname "John" :lname "Dory"}))
(expect ["Mary Dory" "John Dory"]
(with-redefs [users (atom #{{:fname "Mary", :lname "Dory"} {:fname "John", :lname "Dory"}})]
(all-names)))
scenarios are great, but these days I try to keep things simple with bare expectations whenever possible.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





