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

时间:2017-04-11 14:30:10

标签: clojure mocking clojurescript

我想了解with-redefswith-redefs-fn之间的区别。

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

2 个答案:

答案 0 :(得分:11)

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

e.g。

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

vs

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

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

答案 1 :(得分:5)

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

有关Clojure var如何工作的说明,请参阅此问题:When to use a Var instead of a function?它类似于C指针。

在clojure中,当你看到foo时,它就是一个符号。当您看到#'foo时,它是(var foo)的快捷方式,它是一种“特殊形式”(即内置的Clojure,而不是常规函数),它返回var foo {1}}指向。 var依次指向foo的值。