I would like to understand difference between with-redefs and with-redefs-fn.
Concrete examples would be great to understand the fns behaviours.
I would like to understand difference between with-redefs and with-redefs-fn.
Concrete examples would be great to understand the fns behaviours.
They're basically the same, the main difference is that with-redefs lets you write out the body explicitly (like in a let), while with-redefs-fn requires a function as the argument, so you may need to wrap what you want in a lambda. Additionally, with-redefs lets you provide bindings using a vector (again, like let), while with-redefs-fn wants a map. I'd argue that both of these differences are just superficial.
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")))))
In fact, with-redefs is defined in terms of with-redefs-fn, and basically just wraps the body in an anonymous function before passing everything to with-redefs-fn: https://github.com/clojure/clojure/blob/e3c4d2e8c7538cfda40accd5c410a584495cb357/src/clj/clojure/core.clj#L7404
I would ignore with-redefs-fn and use only with-redefs since it is simpler and has the same abilities. Also, beware that the notation #'http/post requires you to use the var for http/post, not the function itself.
For a description of how a Clojure var works, please see this question: When to use a Var instead of a function? It is similar to a C pointer.
In clojure, when you see foo, it is a symbol. When you see #'foo, it is a shortcut for (var foo) which is a "special form" (i.e. a Clojure built-in, not a regular function), which returns the var that foo points to. The var in turn points the the value of foo.