如何获得对类似测试装置的多次引用

时间:2017-09-12 07:03:27

标签: clojure

我正在创建一个在我的测试中使用的灯具。我将灯具绑定到动态符号,以便我可以在测试中引用它。

(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的符号。有没有办法做我想要的,或者我可以采取更好的方法?

1 个答案:

答案 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)]