请分享您的观点,参加2024 Clojure状况调查!

欢迎!请参阅关于页面获取更多关于此如何工作的信息。

+1
Spec

函数有时可能会抛出期望的异常。例如,函数fn / 可能会抛出DivisionByZeroException。我该如何使用spec来捕获它?

3 个回答

+2

选为最佳回答者
 
最佳答案

简单的回答是“你不需要这样做”。Spec可以讨论数据的结构和函数的转换行为,但异常绕过了这种行为:异常意味着该函数没有可以指定的结果。

因此,如果函数将抛出异常,我就不能进行任何生成性测试或函数仪器来检查函数的正确性?
生成测试涉及到在数百或数千次执行一个函数,使用随机生成的符合要求的参数,并检查该函数的结果是否满足预期。异常不是一个结果,所以,你不能在抛出异常的函数上进行生成测试——除非你非常具体地定义参数,只使用能够返回结果的值(这正是Nikola的回答所暗示的)。
+2

与你问题相关的方法是将你的异常转换为数据。

允许异常在代码中流动可能导致不必要的复杂。你可以将可能抛出异常的代码包裹在try/catch中,并将异常转换为数据。

一旦异常从函数回传成为数据,它就回到了spec的领域。

你可以在cognitect-labs/anomalies库中看到这种方法。

同样,ex-info允许你将数据附加到异常上。

+1

Spec定义应该使异常成为不可能

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

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

当启用仪表(在开发/测试期间)时,如果你将0传递给myfn作为y参数,它将立即失败。请参阅:仪表化和测试

...