【问题标题】:How to use `with-redefs` to always throw exception from a function如何使用`with-redefs`总是从函数中抛出异常
【发布时间】:2015-11-10 08:42:37
【问题描述】:

我想对我的代码的异常处理部分进行单元测试。为了做到这一点,我使用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)

with-redefs 中使用(constantly (throw... 或仅断言使用thrown? 引发异常也会导致相同的错误。

基本上我在寻找constantly 的宏版本。

【问题讨论】:

    标签: unit-testing clojure


    【解决方案1】:

    constantly 是函数,而不是宏,所以(constantly (throw ...)) 会立即抛出错误。

    如果你想要一个每次调用都会抛出错误的函数,你需要类似的东西:

    (with-redefs [clj-http/get (fn [& _] (throw (ex-info "unexpected error"
                                                         {:cause "A terrible calamity"})))]
      ...)
    

    【讨论】:

    • 这是我一直在寻找的答案。我将编辑我的问题以更好地反映这一点。
    【解决方案2】:

    您以错误的方式处理此问题:您的测试期望 clj-http 的正常行为返回状态 500,但您的 with-redef 实际上完全覆盖了任何 clj-http 代码。换句话说,您的测试表明所有对clj-http/get 的调用现在总是(constantly) 引发异常。相反,您想要的是 clj-http/get 始终返回 500。您可以使用 clj-http-fake 来做到这一点。

    【讨论】:

      【解决方案3】:

      您还可以使用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))))))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-13
        • 2012-08-23
        • 1970-01-01
        • 1970-01-01
        • 2016-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多