2024 Clojure调查问卷中分享您的想法!

欢迎!请查看关于页面以获取更多关于如何使用此功能的信息。

+1
Spec

有时函数可能会抛出预期的异常。例如,func / 可能会抛出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,则会快速失败。请参阅: 仪表化和测试

...