情况是这样的:我试图对调用函数B的函数A进行单元测试。函数B在弹弓尝试+块中被调用,在某些情况下它可以使用弹弓投掷+。我想在midje测试中模拟函数B,以便它返回try+块中的catch将实际捕获的内容。但我似乎无法创造出正确的投掷方式。下面是代码和测试的大致草图:
(defn function-A
[param]
(try+
(function-B param)
(catch [:type :user-not-found]
(do-something))))
(defn function-B
[param]
(throw+ [:type :user-not-found]))
(fact "do-something is called"
(function-A "param") => (whatever is the result of calling do-something)
(provided
(function-B "param") =throws=> (clojure.lang.ExceptionInfo. "throw+: {:type :user-not-found}"
{:object {:type :user-not-found}, :environment {}}
nil)))
我抛出的ExceptionInfo似乎是正确的。当我的应用程序运行大量的prn语句时,我可以看到这一点。然而,无论我怎么做,我都不能让测试工作。
我还尝试了下面的代码,看看我是否能理解这个问题。然而,虽然这两段代码似乎涉及相同的异常,但只有一个(纯弹弓)设法捕获并打印"捕获它"。我想如果我能理解为什么一个能工作而另一个不能,我就能解决单元测试的问题了。
(try+
(try
(throw+ {:type :user-not-found})
(catch Exception e
(prn "Caught: " e)
(prn "Class: " (.getClass e))
(prn "Message: " (.getMessage e))
(prn "Cause: " (.getCause e))
(prn "Data: " (.getData e))
(throw e)))
(catch [:type :user-not-found] p
(prn "caught it")))
(try+
(try
(throw (clojure.lang.ExceptionInfo. "throw+: {:type :user-not-found}"
{:object {:type :user-not-found}, :environment {}}
nil))
(catch Exception e
(prn "Caught: " e)
(prn "Class: " (.getClass e))
(prn "Message: " (.getMessage e))
(prn "Cause: " (.getCause e))
(prn "Data: " (.getData e))
(throw e)))
(catch [:type :user-not-found] p
(prn "caught it")))
这是一个非常晚的响应,但是下面的解决方案如何:
(defn ex+ [cause]
(try
(throw+ cause)
(catch Throwable ex
ex)))
使用例子:
(broken-fn) =throws=> (ex+ {:type :user-not-found})
好处是你不需要依赖于Slingshot的内部实现
在slingshot生成throwable的代码(参见这里,这里和这里)之后,我发现了以下(有些人为的)方法来生成一个可以在仅throw
时工作的throwable。
(s/get-throwable (s/make-context {:type :user-not-found} "throw+: {:type :user-not-found}" (s/stack-trace) {}))
呈现您期望从示例中得到的结果。
(try+
(try
(throw (s/get-throwable (s/make-context {:type :user-not-found} "throw+: {:type :user-not-found}" (s/stack-trace) {})))
(catch Exception e
(prn "Caught: " e)
(prn "Class: " (.getClass e))
(prn "Message: " (.getMessage e))
(prn "Cause: " (.getCause e))
(prn "Data: " (.getData e))
(throw e)))
(catch [:type :user-not-found] p
(prn "caught it")))
希望能有所帮助。