I'm creating a fixture to use in my tests. I bind the fixture to a dynamic symbol so that I can refer to it in my tests.
(def ^:dynamic *thing-doer* nil)
(defn with-thing-doer
[config]
(fn [f]
(binding [*thing-doer* (create-thing-doer config)]
(try
(.start *thing-doer*)
(f)
(finally
(.close *thing-doer*))))))
(use-fixtures :each
(join-fixtures [(with-thing-doer a-config)]))
(deftest an-example-test
(do-it! *thing-doer* thing)
(is (= 1 (count (things-done)))))
This works great, but in some tests I need a few of these fixtures, with just slight differences between each. There are enough combinations that I don't want to create a separate dynamic symbol for each and every one. I'd rather that be defined in the test file that's setting up the fixtures. Something like:
(defn with-thing-doer
[doer config]
(fn [f]
(binding [doer (create-thing-doer config)]
(try
(.start doer)
(f)
(finally
(.close doer))))))
(def ^:dynamic *thing-doer-a* nil)
(def ^:dynamic *thing-doer-b* nil)
(use-fixtures :each
(join-fixtures [(with-thing-doer *thing-doer-a* a-config)
(with-thing-doer *thing-doer-b* b-config)]
However it seems that the symbol given to binding
needs to be known at compile time. Is there a way to do what I want, or a better approach I could take?
You can use with-bindings to create bindings dynamically. This way bound vars do not need to be known at compile time.
Your with-thing-doer
function would look like the following:
(defn with-thing-doer
[doer config]
(assert (var? doer))
(fn [f]
(with-bindings {doer (create-thing-doer config)}
(try
(.start @doer)
(f)
(finally
(.stop @doer))))))
You need to pass the first parameter as a var object.
(use-fixtures :each
(join-fixtures [(with-thing-doer #'*thing-doer-a* a-config)
(with-thing-doer #'*thing-doer-b* b-config)]