Clojure 在doseq中与redefs一起使用
我有一个环处理程序,它使用几个函数来构建响应。如果这些函数中的任何一个抛出异常,则应捕获该异常,以便在返回500之前编写自定义响应正文 我正在为处理程序编写单元测试,我希望确保上述任何函数引发的异常都能得到处理。我的本能是在Clojure 在doseq中与redefs一起使用,clojure,mocking,Clojure,Mocking,我有一个环处理程序,它使用几个函数来构建响应。如果这些函数中的任何一个抛出异常,则应捕获该异常,以便在返回500之前编写自定义响应正文 我正在为处理程序编写单元测试,我希望确保上述任何函数引发的异常都能得到处理。我的本能是在doseq中使用redefs: (doseq [f [ns1/fn1 ns1/fn2 ns2/fn1]] (with-redefs [f (fn [& args] (throw (RuntimeException. "fail!"))] (let [res
doseq
中使用redefs:
(doseq [f [ns1/fn1 ns1/fn2 ns2/fn1]]
(with-redefs [f (fn [& args] (throw (RuntimeException. "fail!"))]
(let [resp (app (request :get "/foo")))))]
(is (= (:status resp) 500))
(is (= (:body resp) "Something went wrong")))))
当然,考虑到使用redefs的
想要更改vars的根绑定,它将f
视为一个符号。有没有办法让它重新绑定f
所指的var?我想我需要一个宏来完成这一点,但我希望有人能想出一个聪明的解决方案。使用redefs
只是对alter var root
的重复调用的一种安慰,所以你可以自己编写被删除的表单,比如:
(doseq [v [#'ns1/fn1 #'ns1/fn2 #'ns2/fn1]]
(let [old @v]
(try
(alter-var-root v (constantly (fn [& args]
(throw (RuntimeException. "fail!")))))
(let [resp (app (request :get "/foo")))
(is (= (:status resp) 500))
(is (= (:body resp) "Something went wrong")))
(finally (alter-var-root v (constantly old))))))
下面是我编写的用于测试的实用函数:
(defn with-mocks
"Iterates through a list of functions to-mock, rebinding each to mock-fn, and calls
test-fn with the optional test-args.
Example:
(defn foobar [a b]
(try (+ (foo a) (bar b))
(catch Exception _ 1)))
(deftest test-foobar
(testing \"Exceptions are handled\"
(with-mocks
[#'foo #'bar]
(fn [& _] (throw (RuntimeException. \"\")))
(fn [a b] (is (= 1 (foobar a b)))) 1 2)))"
[to-mock mock-fn test-fn & test-args]
(doseq [f to-mock]
(let [real-fn @f]
(try
(alter-var-root f (constantly mock-fn))
(apply test-fn test-args)
(finally
(alter-var-root f (constantly real-fn)))))))
在问这些问题之前,我真的应该养成阅读Clojure资料的习惯!由于大多数Clojure都是在Clojure中实现的,因此实际上可以理解。当然,这些问题和答案基本上是存在堆栈溢出的理由@如果你想添加一个答案,请添加一个你自己的答案,而不是编辑一堆我从来没有在我的答案中说过的东西。很抱歉。我认为它很适合你的答案,因为它使用了你的代码。我真的不确定是否要添加一个新的答案,是否要添加它作为我问题的更新,或者是什么。无论如何,如果这是最合适的做法,我会把它作为一个新的答案添加进去。再次抱歉!