我正在创建一个在我的测试中使用的灯具。我将灯具绑定到动态符号,以便我可以在测试中引用它。
(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)))))
这很好用,但在某些测试中我需要一些这样的灯具,每个灯具之间只有细微的差别。有足够的组合,我不想为每一个创建单独的动态符号。我宁愿在测试文件中定义设置灯具。类似的东西:
(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)]
然而,似乎需要在编译时知道给binding
的符号。有没有办法做我想要的,或者我可以采取更好的方法?
答案 0 :(得分:4)
您可以使用with-bindings动态创建绑定。这样,在编译时不需要知道绑定的变量。
您的with-thing-doer
功能如下所示:
(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))))))
您需要将第一个参数作为var对象传递。
(use-fixtures :each
(join-fixtures [(with-thing-doer #'*thing-doer-a* a-config)
(with-thing-doer #'*thing-doer-b* b-config)]