请在 2024 年 Clojure 状态调查! 中分享您的想法。

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

+1
Spec

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

共有 3 个回答

+2
 
最佳回答

简单答案是“您不能”。Spec 可以谈论数据的结构以及函数的转换行为,但异常绕过了这种行为:异常意味着函数没有结果可以指定。

那么,如果函数会抛出异常,我就不能进行任何生成测试或函数仪器来检查函数的正确性吗?
生成测试涉及数百或数千次执行一个函数,使用随机生成的符合规定的参数,然后检查该函数结果所期望的性质是否保持。异常不是一个结果,所以不可以在抛出异常的函数上进行生成测试——除非非常具体地定义参数,使其只包含函数可以返回结果的值(这正是指出了Nikola的回答)。
+2

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

让异常穿过代码可能是一个不必要的复杂性。您可以将可能会抛出的代码包装在try/catch中,并将异常转换为数据。

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

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

类似地,ex-info允许您将数据附加到异常。

+1

规格定义应使异常无法发生

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

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

在启用仪表(在开发/测试期间),如果您将0作为y传递给myfn,它将快速失败。请参阅: 仪表和测试

...