Share your thoughts in the 2021 Clojure Community Survey!

Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Spec by

Function sometime might throw expected exception. e.g. fn / might throw DivideByZeroException. How can I caught this using spec?

3 Answers

+2 votes
selected by
Best answer

The simple answer is "you don't". Spec can talk about the structure of data and the transformative behavior of functions but exceptions side-step that behavior: an exception means the function has no result to specify.

So, If the function will throw exception, I cannot do any generative test or function instrument  to check the correctness of the function?
Generative testing involves executing a function hundreds or thousands of times with randomly-generated conforming arguments and then checking that expected properties hold on the result of that function. An exception is not a result, so, no you cannot do generative testing on functions that throw exceptions -- unless you very specifically define the arguments to only be values that the function can return a result for (which is what Nikola's answer hints at).
+2 votes

An approach related to your question is to turn your exceptions into data.

Allowing exceptions to flow though your code can be an unnecessary complication. You could wrap code which might throw in an try/catch and turn the exception into data.

Once your exception is data passed back from the function it's back in the realm of spec.

You can see this approach in the cognitect-labs/anomalies lib.

Similarly ex-info allows you to attach data to your exception.

+1 vote

Spec definition should make exceptions impossible:

(defn myfn [x y] (/ x y))

(s/fdef myfn
  :args (s/cat :x number?
               :y (s/and
                   (complement zero?))))

With instrument turned on (during development / testing), it will fail fast if you pass 0 as y to myfn. See: Instrumentation and Testing.