在 Clojure 中模拟现有方法

Posted

技术标签:

【中文标题】在 Clojure 中模拟现有方法【英文标题】:Mocking existing methods in Clojure 【发布时间】:2014-03-11 10:58:16 【问题描述】:

我正在尝试使用with-redefsreify 来模拟clojure 中的方法。我不知道从哪里开始使用这些。谁能给我一个模拟方法的例子吗?互联网上的文档对我没有帮助,因为我现在完全混淆了。

【问题讨论】:

您是要模拟一个类的方法,还是模拟一个 clojure 函数(用 def 或 defn 定义) @Arthur Ulfeldt :我希望模拟两者 您可能会发现有用的github.com/asyntactic/dynamic-reify 以及函数和变量的基本示例gist.github.com/jaimeagudo/8980813 【参考方案1】:

假设您想监视/模拟/存根函数bar 并测试它在函数foo 中被调用了多少次。一个简单的例子可以是:

(defn bar [] ...)

(defn foo [] 
  (bar)
  (bar)
  (bar))

(deftest 
  (let [args (atom [])]
    (with-redefs [bar (fn [x] (swap! args conj x))] 
      (foo)
      (is (= (count @args) 3)))))

好吧,我同意上面的代码有点乏味。 您可以尝试以下宏: (我将调用历史记录到元数据中)

(defmacro with-mock [vr & body] 
  `(with-redefs [~vr (with-meta 
                       (fn [& ~'args] (swap! (-> ~vr meta :args) conj ~'args))
                       :args (atom []))] 
     (do ~@body)))

用法:

(with-mock bar 
  (foo)
  (is (= (-> bar meta :args deref count)
         3)))

通过一些实用功能,上面的宏可以成为一个强大的工具。 Clojure 的表现力真是太棒了。

【讨论】:

【参考方案2】:

“The Joy of Clojure (Manning)”一书可能是一个很好的起点,“13.2 测试”部分提供了一些关于(以及其他)您提到的技术的信息 - 使用 with-redefs 宏。

【讨论】:

这是本书的第一版。如果您使用的是“The Joy of Clojure”的第 2 版,这已移至第 17.2 节

以上是关于在 Clojure 中模拟现有方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Clojure 1.3 中,如何读写文件

Clojure 的代理与 Scala 的演员相比如何?

Clojure 中的可插拔向量处理单元

在 Clojure 中添加向量的惯用方法是啥?

从clojure中的普通lisp替换(null x)函数的惯用方法

如何在 Clojure 中调用公共类的非公共方法?