为什么不能在 deftest 周围应用 with-redefs?

Gis*_*shu 1 clojure clojure.test

with-redefs 函数似乎正是在 clojure 测试中模拟/存根依赖项所需要的。我正在使用 clojure.test [1.10.1]

最初它让我很伤心,因为在我运行测试时没有应用新的绑定。最后,我得到了以下设置按预期工作。其他命名空间需要依赖项

(ns abc 
  (:require [anotherns.id-gen-mock :as mock])

(deftest test-buy
  (testing "Appends trade to the trades log"
    (let [mock (atom {})]
      (with-redefs [id-gen/get-next-id  mock/get-next-id
                    save-trade          (fn [t] (reset! mock {:trade t}))]
          ... test code

  ))))
Run Code Online (Sandbox Code Playgroud)

现在我意识到,模拟对我的所有测试都是通用的,所以我像这样升级了它。

(with-redefs [id-gen/get-next-id  mock/get-next-id
              save-trade          identity]
  (deftest test-holdings
    (testing "after 1 buy"
      ... test code
        
        
Run Code Online (Sandbox Code Playgroud)

现在不使用新绑定,调用真正的依赖项 - 测试失败。

我在 SO 上看到一些帖子提到了有关“直接链接”的内容,但我无法真正理解为什么它在 Case1 中有效,而在 Case2 中无效。如果我将 with-redefs 移回 deftest 形式,它会再次工作。

Bip*_*ill 5

根据文档字符串(https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs), with-redefs 在执行主体后恢复原始值。在给定的情况下,主体定义了一个测试。With-redefs 因此控制测试的定义,而不是它们的执行。当测试执行时,对 get-next-id 的任何引用都会将该符号解析为其当前值,届时该值将是真实值,而不是模拟值。(这符合逻辑:如果案例 1 成立,并且文档字符串成立,则案例 2 不成立。)

由于评论中已经提到的原因,with-redefs 通常不是首选工具。Clojure 提供了更强大的技术,例如,制作高阶子系统并使用夹具来配置它们以进行测试。