我想单元测试代码的异常处理部分。为了做到这一点,我使用with-redefs
来重新绑定可以抛出异常以在测试期间抛出异常的API。我的测试功能看起来像这样
(deftest exception-handling
(testing "Map exception to Ring-response map"
(with-redefs [clj-http/get
(constantly (throw (ex-info "unexpected error" {:cause "A terrible calamity"})))]
(is (= 500
(:status
(some-function-calling-http-get arg))))
)
)
)
运行lein test
会导致错误消息:
ERROR in (exception-handling) (core.clj:4593)
Uncaught exception, not in assertion.
expected: nil
actual: clojure.lang.ExceptionInfo: unexpected error
at clojure.core$ex_info.invoke (core.clj:4593)
在(constantly (throw...
中使用with-redefs
或仅声明thrown?
引发异常也会导致同样的错误。
基本上我正在寻找constantly
的宏观版本。
答案 0 :(得分:4)
constantly
是一个函数,而不是宏,因此(constantly (throw ...))
会立即抛出错误。
如果你想要一个每次调用都会抛出错误的函数,你需要这样的东西:
(with-redefs [clj-http/get (fn [& _] (throw (ex-info "unexpected error"
{:cause "A terrible calamity"})))]
...)
答案 1 :(得分:1)
您正在以错误的方式接近此问题:您的测试期望clj-http的正常行为返回状态500,但您的with-redef
实际上完全覆盖了任何clj-http代码。换句话说,您的测试显示现在对clj-http/get
的所有调用始终(constantly
)都会引发异常。你想要的是clj-http/get
总是返回500.你可以使用clj-http-fake来做到这一点。
答案 2 :(得分:0)
您还可以使用clj-http-fake模拟对外部世界的HTTP调用,例如。
(with-fake-routes {
"http://external.api" (fn [request] {:status 500 :headers {} :body "Exception"}
(is (= 500
(:status
(some-function-calling-http-get arg))))))