如何使用thrown-with-msg在测试中捕获IllegalArgumentException?

时间:2013-06-28 16:36:58

标签: unit-testing macros clojure

我尝试测试异常的抛出:

;;; src
;; Courtesy https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj
(defmacro assert-args [& pairs]
  `(do (when-not ~(first pairs)
         (throw (IllegalArgumentException.
                 (str (first ~'&form) " requires " ~(second pairs) " in " ~'*ns* ":" (:line (meta ~'&form))))))
       ~(let [more (nnext pairs)]
          (when more
            (list* `assert-args more)))))

(defmacro my-macro []
  (assert-args false "foobar")
  #_(...))

;;; test
(deftest x-fn-test
  (is (thrown-with-msg? IllegalArgumentException #"foo" (my-macro))))

但是没有一个例外被测试框架捕获,但都抛出了。

2 个答案:

答案 0 :(得分:2)

您的throw表达式格式错误,您想要

(throw (IllegalArgumentException. "foo"))

完整的工作代码:

(ns mytest.core
  (:use clojure.test))

(defn x-fn []
  (throw (IllegalArgumentException. "foo")))

(deftest x-fn-test
  (is (thrown-with-msg? IllegalArgumentException           #"foo"     (x-fn)))
  (is (thrown-with-msg? IllegalArgumentException           #".*foo.*" (x-fn)))
  (is (thrown-with-msg? IllegalArgumentException           #"^foo$"   (x-fn)))
  (is (thrown-with-msg? java.lang.IllegalArgumentException #"foo"     (x-fn)))
  (is (thrown-with-msg? java.lang.IllegalArgumentException #".*foo.*" (x-fn)))
  (is (thrown-with-msg? java.lang.IllegalArgumentException #"^foo$"   (x-fn))))


; nREPL 0.1.8-preview
user> 
#<Namespace mytest.core>
mytest.core> (run-tests)

Testing mytest.core

Ran 1 tests containing 6 assertions.
0 failures, 0 errors.
{:type :summary, :pass 6, :test 1, :error 0, :fail 0}

答案 1 :(得分:1)

仍然抛出异常的原因是因为宏(my-macro)在编译期间被扩展,调用(assert-args)宏,因此在编译期间抛出异常。我的错误是假设在测试中调用(my-macro)将在运行时触发异常并让测试(thrown-with-msg?)捕获它。

所以错误的假设是嵌套宏的代码只在编译期间扩展,而不是执行。如果(my-macro)是一个函数,那就可以了。