【问题标题】:Why can't with-redefs be applied around a deftest?为什么不能在 deftest 周围应用 with-redefs?
【发布时间】:2023-04-07 11:36:02
【问题描述】:

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

  ))))

现在我意识到,我的所有测试都可以使用模拟,所以我将它向上移动。

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

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

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

【问题讨论】:

  • 你正在测试的代码是惰性的还是在不同的线程中运行?
  • @cfrick - 没有线程或惰性序列 AFAIK。只需调用模拟依赖项,然后进行原子集合/映射更新。

标签: clojure clojure.test


【解决方案1】:

根据docstring(https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs),with-redefs在执行body后恢复原值。在给定的情况下,主体定义了一个测试。因此,with-redefs 控制测试的定义,但不控制它们的执行。当测试执行时,任何对 get-next-id 的引用都会将该符号解析为其当前值,到那时它将是真实的,而不是模拟的。 (这在逻辑上是这样的:如果 case No.1 成立,并且 docstring 成立,那么 case No.2 不能成立。)

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

【讨论】:

    猜你喜欢
    • 2017-09-07
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2012-08-29
    • 2019-11-29
    相关资源
    最近更新 更多