在Clojure中with-redefs和with-redefs-fn有什么区别?

Ert*_*tin 10 clojure mocking clojurescript

我想了解with-redefs和之间的区别with-redefs-fn.

具体的例子可以很好地理解fns行为.

Ale*_* C. 12

它们基本相同,主要的区别在于with-redefs可以让你明确地写出正文(比如a let),同时with-redefs-fn需要一个函数作为参数,所以你可能需要在lambda中包装你想要的东西.此外,with-redefs您可以使用矢量(同样let)提供绑定,同时with-redefs-fn需要地图.我认为这两种差异都只是肤浅的.

例如

(with-redefs [http/post (fn [url] {:body "Goodbye world"})]
  (is (= {:body "Goodbye world"} (http/post "http://service.com/greet"))))
Run Code Online (Sandbox Code Playgroud)

VS

(with-redefs-fn {#'http/post (fn [url] {:body "Goodbye world"})}
      (fn [] (is (= {:body "Goodbye world"} (http/post "http://service.com/greet")))))
Run Code Online (Sandbox Code Playgroud)

事实上,它with-redefs是根据而定义的with-redefs-fn,并且基本上只是在将所有内容传递给匿名函数之前将其包装with-redefs-fn:https://github.com/clojure/clojure/blob/e3c4d2e8c7538cfda40accd5c410a584495cb357/src/clj/clojure/core.clj# L7404


Ala*_*son 5

我会忽略with-redefs-fn并仅使用with-redefs它,因为它更简单并且具有相同的功能。另外,请注意,该符号#'http/post要求您将var用于http/post,而不是函数本身。

有关Clojure的var工作原理的描述,请参见以下问题: 什么时候使用Var而不是函数? 它类似于C指针。

在Clojure中,当您看到时foo,它是一个符号。当你看到#'foo,这是一个快捷方式(var foo)是一种“特殊形式”(即Clojure的内置,而不是常规的函数),它返回的var那个foo点。该var反过来点的值foo