Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
(defn serialize-exception [e]
{:message (.getMessage e)
:ex-data (ex-data e)
:stack-trace (map bean (.getStackTrace e))
:cause (if-let [cause (.getCause e)]
(serialize-exception cause))})
(defn ->StackTraceElement [{:keys [className methodName fileName lineNumber]}]
(StackTraceElement. className methodName fileName lineNumber))
(defn deserialize-exception
"Returns mocked Exception from serialized data.
Only overrides getStackTrace, which is used at least by clojure.stacktrace/print-stack-trace
and Boot to print the stacktrace. Some other stuff could call directly to
printStackTrace."
[{:keys [message ex-data stack-trace cause]}]
(let [cause (if cause (deserialize-exception cause))
stack-trace (into-array StackTraceElement (map ->StackTraceElement stack-trace))]
(if ex-data
(proxy [ExceptionInfo] [message ex-data cause]
(getStackTrace []
stack-trace))
(proxy [Throwable] [message cause]
(getStackTrace []
stack-trace)))))
(deftest basic-exception-test
(let [original (Exception. "foo")
a (deserialize-exception (serialize-exception original))]
(is (= "foo" (.getMessage a)))))
(deftest ex-data-test
(let [original (ex-info "foo" {:a 1})
a (deserialize-exception (serialize-exception original))]
(is (= "foo" (.getMessage a)))
(is (= {:a 1} (ex-data a)))))
(deftest cause-test
(let [original (Exception. "foo" (Exception. "bar"))
a (deserialize-exception (serialize-exception original))]
(is (= "bar" (.getMessage (.getCause a))))))
(defn drop-first-line [s]
(-> s
(string/split #"\n")
rest
(->> (string/join "\n"))))
(deftest stack-trace-test
; First line differs as it contains the name of Exception class
(let [original (Exception. "foo")
a (deserialize-exception (serialize-exception original))]
(is (= (drop-first-line (with-out-str (st/print-stack-trace original)))
(drop-first-line (with-out-str (st/print-stack-trace a)))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment