请在2024年Clojure现状调查中分享你的想法!

欢迎!请查看关于页面以了解更多关于这个工作原理的信息。

+1 投票
in Spec by

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

3 个答案

+2 投票
by
selected by
 
最佳答案

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

by
那么,如果函数会抛出异常,我就不能进行任何生成性测试或函数工具来解决函数的正确性检查吗?
生成测试涉及多次执行一个函数,使用随机生成的符合要求的参数,然后检查结果的预期属性是否保持不变。异常不是一个结果,所以,你不能在抛出异常的函数上进行生成测试——除非你非常具体地定义参数只使用函数可以返回结果的值(这正是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,它会快速失败。参阅: 仪器化和测试

...