Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write a test to handle an expected exception?

How can I test for a function that throws an expected exception? Here is the function that throws the exception:

(defn seq-of-maps?
  "Tests for a sequence of maps, and throws a custom exception if not."
  [s-o-m]
  (if-not (seq? s-o-m)
    (throw (IllegalArgumentException. "s-o-m is not a sequence"))
    (if-not (map? (first s-o-m))
      (throw (IllegalArgumentException. "s-o-m is not a sequence of maps."))
      true)))

I want to design a test like the following in which an exception is thrown and caught and then compared. The following does not work:

(deftest test-seq-of-maps
  (let [map1  {:key1 "val1"}
        empv  []
        s-o-m (list {:key1 "val1"}{:key2 "val2"})
        excp1 (try 
                (seq-of-maps? map1)
                (catch Exception e (.getMessage e)))]
    (is (seq-of-maps? s-o-m))
    (is (not (= excp1 "s-o-m is not a sequence")))))

I am getting these errors:

Testing util.test.core

FAIL in (test-seq-of-maps) (core.clj:27)
expected: (not (= excp1 "s-o-m is not a sequence"))
  actual: (not (not true))

Ran 2 tests containing 6 assertions.
1 failures, 0 errors.    

Obviously, I am missing something about writing tests. I am having trouble figuring that out. My project was set up with lein new, and I am running the tests with lein test.

Thanks.

like image 885
octopusgrabbus Avatar asked Aug 15 '12 16:08

octopusgrabbus


People also ask

How do you assert expected exception?

When using JUnit 4, we can simply use the expected attribute of the @Test annotation to declare that we expect an exception to be thrown anywhere in the annotated test method. In this example, we've declared that we're expecting our test code to result in a NullPointerException.

How can you use JUnit for testing a code that throws a desired exception?

JUnit provides an option of tracing the exception handling of code. You can test whether the code throws a desired exception or not. The expected parameter is used along with @Test annotation. Let us see @Test(expected) in action.


1 Answers

The last assertion in your test is incorrect; it should be (is (= excp1 "s-o-m is not a sequence")) since map1 isn't a seq of maps.

Aside from that, it's probably clearer to use (is (thrown? ..)) or (is (thrown-with-msg? ...)) to check for thrown exceptions.

Example:

(t/is (thrown? java.lang.ClassCastException (s/valid? ::sut/int-value "x"))))

Note that you just write classname as a symbol. Use java.lang.Exception if you don't care about the exact Exception.

like image 176
Joost Diepenmaat Avatar answered Oct 04 '22 20:10

Joost Diepenmaat