Checking for specific exception characteristics in clojure.test

TLDR: What is the correct way to test for a thrown ex-info using clojure.test?

I have the following code which I’d like to write a test for using clojure.test

(fn [type functions]
  (cond (= wrt :sigma)
        :epsilon         
        
        (= wrt :epsilon)    
        :empty-set
        
        :else
        (throw (ex-info (format "cannot compute derivative of :sigma wrt %s because they intersecting" wrt)
                        {:type :derivative-error
                         :derivative {:expr expr
                                      :type type
                                      :wrt wrt
                                      :functions functions}
                         :cause :intersecting-types
                         
                         }))))

I see in the clojure.test documentation that I can use the idiom (is (thrown? ...)). But it is not clear how to get the exception object using thrown? and test for the keys of the hashmap which I’ve designated at the call to ex-info.

1 Like

There’s thrown-with-msg? but that doesn’t help with ex-info. This is one of the reasons I prefer expectations/clojure-test (which I maintain):

  (is (thrown-with-msg? ArithmeticException #"Divide by zero" (/ 1 0)))
  (expect (more-> ArithmeticException type
                  #"Divide by zero"   ex-message)
          (/ 1 0))

You could also use ex-info in more-> and drill down into parts of that data to “expect” its structure and content.

https://cljdoc.org/d/expectations/clojure-test/1.2.1/doc/expecting-more

3 Likes

I use Nubank’s Matcher Combinators lib. Mainly for diffing expected and provided nested maps. But it also extends clojure.test's is to provide thrown-match?

This is a good question, as I use ex-info too. I think I’d wrap a try-catch block in my is (untested):

(is (try
      (do myfn false) ;; It's supposed to throw something
      (catch Exception e
        (let [dat (ex-data e)]
          (or 
           (some-scrutinize-fn dat) ;; error threw the right stuff!
           false)))))