如何在 Clojure 中 运行 单元测试时抑制异常输出

How to suppress output of exception while running unit tests in Clojure

我正在为 clojure 使用 leiningen,并且我有一套单元测试 运行 当我 运行 lein test.

我注意到在一些测试中,我们想要测试异常处理场景,为此我们抛出了一个异常。 问题是,它 returns 命令行中的完整堆栈跟踪,我经常认为发生了一些不好的事情,但实际上并没有。

来自 JS 世界,我看到我们可以抑制我们想在像 jest 这样的框架中将其标记为抑制的异常,leiningen 或 clojure 有什么选择吗?

我最喜欢的方式是使用tupelo.test library as demonstrated in this template project。例如:

(ns tst.demo.core
  (:use tupelo.core tupelo.test))

(dotest
  (is= 5 (+ 2 3))
  (throws? (/ 1 0)))

结果

-----------------------------------
   Clojure 1.10.3    Java 15.0.2
-----------------------------------

Testing tst.demo.core

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

如果throws?中的表达式不抛出异常,它将失败。否则为及格。

这在幕后使用 try/catch,您也可以随时手动执行。


如果你真的不想使用某个库,你可以在clojure.test中使用。您需要使用如下语法:

(is (thrown? ArithmeticException (/ 1 0))) 

但是,请注意此功能很脆弱,如果您犯了错误,您将不会收到任何警告。这就是我编写包装器 tupelo.test/throws? 的原因,因为它既简单又防弹。

由于 Tupelo 库是开源的,如果需要,您可以随时复制源代码:

(defmacro throws? 
  "Use (throws? ...) instead of (is (thrown? ...)) for clojure.test. Usage:
     (throws? (/ 1 0))                      ; catches any Throwable"
  [& forms]
  `(clojure.test/is
     (try
       ~@forms
       false ; fail if no exception thrown
       (catch Throwable dummy#
         true)))) ; if anything is thrown, test succeeds

所以你可以看到所有 throws? 宏所做的就是将你的代码包装在 try/catch 中,然后 return truefalse 到标准 clojure.test/is 形式。