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

欢迎!请参阅关于页面以了解更多关于这一机制的信息。

+1
Spec

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

3 个答案

+2
by
 
最佳答案

简单的答案是“你不需要”。Spec可以谈论数据的结构和函数的转换行为,但异常避开了这种行为:异常意味着函数没有可指定的结果。

by
所以,如果函数会抛出异常,我就无法进行任何生成测试或函数仪器测试来检查函数的正确性吗?
生成测试涉及执行函数数百或数千次,使用随机生成的符合规范的参数,然后检查该函数的结果是否保持预期的属性。异常不是一个结果,所以,你不能在抛出异常的函数上进行生成测试,除非你明确地定义参数只包含函数可以返回结果值的值(这正是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 作为 y 参数传递给 myfn,程序将快速失败。参见: 仪器化和测试

...